pax_global_header00006660000000000000000000000064133731410520014511gustar00rootroot0000000000000052 comment=ba29fa57b2455143dd86973c2229d6f7b8e16d9b OpenDKIM-rel-opendkim-2-11-0-Beta2/000077500000000000000000000000001337314105200164555ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/.gitattributes000066400000000000000000000000231337314105200213430ustar00rootroot00000000000000www/ export-ignore OpenDKIM-rel-opendkim-2-11-0-Beta2/.gitignore000066400000000000000000000007511337314105200204500ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno *.orig *.rej t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure.scan configure.lineno aclocal.m4 depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile *.tar.gz *.tar.gz.md5 *.tar.gz.sha1 *.tar.gz.asc tags .deps autom4te.cache core *.core build-aux opendkim-[0-9].[0-9].[0-9] .vscode OpenDKIM-rel-opendkim-2-11-0-Beta2/BRANCHES000066400000000000000000000042061337314105200175670ustar00rootroot00000000000000 OpenDKIM Branch Listing ~~~~~~~~~~~~~~~~~~~~~~~ Production Branches ~~~~~~~~~~~~~~~~~~~ master releases only develop ongoing development Experimental Branches (branch name contains owner) ~~~~~~~~~~~~~~~~~~~~~ exp-msk-doxygen Experimenting with doxygen (automatic libopendkim doc generation) Closed Branches ~~~~~~~~~~~~~~~ br-1-1 v1.1.x releases br-1-2 v1.2.x releases br-2-0 v2.0.x releases br-2-1 v2.1.x releases br-dblack-autoimprovements m4 subdirectory for macros pkg-config detection pkg-conf delivery of .pc files for our libraries full FEATURE and FFR_FEATURE macros in configure.ac man page generation for opendkim (include doco for FFR bits and tag experimental in man pages if enabled) br-dblack-codecoverage Generate code coverage testing from lcov/gcov/gprof (http://ltp.sourceforge.net/coverage/lcov.php) br-msk-adsp-lists Add ADSP-specific features for MLMs. br-msk-default-sender Default sender setting br-msk-generic-dns Generic DNS facilities. br-msk-ldap-caching Experimental LDAP query piggybacking and caching br-msk-libprofiling Optimizations based on some recent gprof output br-msk-lua Experimenting with LUA for scriptable policy hooks br-msk-lua-dataset Experimental addition of a new "lua:" dataset type. br-msk-lua-dbs Support for abitrary data set operations from Lua scripts. br-msk-openldap OpenLDAP integration work br-msk-reduce-symbols Build automation to limit exported library symbols br-msk-resign _FFR_RESIGN (binding of handles for message resigning) br-msk-single-auth-result Feature request #SF2981598: Add "SingleAuthResult" and "NoHeaderB" settings. br-msk-solaris-cleanup Extensive reworking of various things so a build on Solaris with the native compiler is clean (bug #SF2903325) br-msk-stats-update Update to statistics code to support required reporting features missed in the 2.1.x line. br-msk-stats-redux Overhaul of statistics collection and reporting code. br-msk-yahoo-fixes Bug fixes and feature requests for Yahoo! br-sm-resign-features Resign-related features (see SourceForge) exp-msk-reputation DKIM-based domain reputation R&D OpenDKIM-rel-opendkim-2-11-0-Beta2/FEATURES000066400000000000000000000100301337314105200176100ustar00rootroot00000000000000 F E A T U R E S F O R F U T U R E R E L E A S E INTRODUCTION ============ In the source code for this package may be one or more segments of code that are disabled, as they are slated for future release (FFR). These are generally unreleased or incomplete features, or can be new algorithms for existing features. They are often untested and currently unsupported, and generally formally become part of the released software in some future revision. There may or may not be documentation for them outside of this file. Use them at your own risk. To enable an FFR in the source code, specify "--enable-featurename" when executing "./configure". For example, to add the "widget" feature, you would add "--enable-widget" when executing "./configure". FEATURES ======== Feature Name Description allsymbols By default, the build will attempt to create a libopendkim that only exports symbols intended to be exported; internal-only functions are not visible. This feature exports those as well. This is intended only for running library unit tests. (libopendkim) atps Support for experimental Authorized Third-Party Signatures mechanism. (opendkim, libopendkim) conditional Conditional signatures. EXPERIMENTAL (opendkim, libopendkim) db_handle_pools Database handle pools. EXPERIMENTAL (opendkim) default_sender Allow declaration of sender address to use when a message contains no obvious sender. (opendkim) diffheaders When verification fails for a message for which a "z=" tag was provided, compare the received headers to the original headers to look for possible munging. Requires the tre library, available at http://laurikari.net/tre. (opendkim, libopendkim) identity_header Enable selection of an identity for signing based on the value found in a particular header. (opendkim) ldap_caching Adds code that ensures duplicate LDAP queries aren't sent and local caching of LDAP replies is done. Note that this means changes made to LDAP data won't be recognized by the filter right away. (opendkim) postgres_reconnect_hack libpq (the postgresql client library) fails to identify at least some error conditions as needing a connection to be restarted before a query can be completed. This code compensates for that problem by checking for fatal errors in ad different (but unconventional) manner. It is hoped that this can be removed in the near future. (opendkim) rate_limit Experimental rate limiting based on confirmed signer domains. (opendkim) rbl Option to query realtime blacklists from within Lua scripts. Requires Lua. (opendkim) replace_rules Allow specification of a "replacement rules" table for use when signing, replacing certain patterns in address headers with specific strings to anticipate the effects of such things as the "masquerade" and "genericstable" features of the sendmail MTA. (opendkim) reprrd Support for collaborative reputation that uses rrdtool. EXPERIMENTAL (opendkim) reputation Support for a collaborative reputation system. EXPERIMENTAL (opendkim) reputation_cache Temporary caching of reputation replies to reduce round trips to the reputation server. EXPERIMENTAL (opendkim) resign Experimental API features for simultaneous verifying and re-signing of a single message. (libopendkim, opendkim) sender_macro Enable control over an MTA macro from which the address of the sender is taken, rather than from header fields. (opendkim) socketdb Adds support for arbitrary socket-based data sets. (opendkim) stats Optional generation of per-message and per-signature statistics of interest to the evolution of DKIM. See stats/README for information. (opendkim) statsext Support for localized stats extensions. See stats/README for information. (opendkim) vbr Enable VBR (Vouch By Reference) header field addition (outbound) and processing (inbound). (opendkim) COPYRIGHT ========= Copyright (c) 2009, Sendmail, Inc. and its suppliers. All rights reserved. Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/HowToRelease000066400000000000000000000032621337314105200207440ustar00rootroot00000000000000Release procedures for OpenDKIM 0) Run "./copyright-check" to ensure anything updated in the current year has a current copyright notice in it. 1) Edit configure.ac so that the new release number is formed with the VERSION_RELEASE* macros. 2) In the root build directory, do these things: % make distclean % autoreconf % ./configure % make % make distcheck This will produce an opendkim-(version).tar.gz tarball after running all unit tests. 3) Commit changes made to RELEASE_NOTES to the SourceForge git repository. Be sure to include any open feature requests, patches or bug fixes from the SourceForge trackers. 4) Prepare a release announcement by using the file "announcement" from git as your template. Change the From: to the name and address of the person making the announcement. Make sure that address has permissions to post to opendkim-users and opendkim-announce. There should be a paragraph or two at the top highlighting the interesting changes and indicating what the main focus of this release is (new features, bug fixes, etc.), and then the full RELEASE_NOTES block for the new release. Commit this to git. 5) Merge the "develop" branch to the "master" branch, as follows: % git checkout master % git merge develop [massage in and commit any conflicts] % git push 6) Deploy all needed files to SourceForge by doing 'make push'. This will also place the release tag. 7) Via the SourceForge UI, make the latest tarball the default download for all operating systems. 8) Send the release announcement: % sendmail -t < announcement 9) Mark any bug fixes or feature requests, etc. as closed if this release contained them. OpenDKIM-rel-opendkim-2-11-0-Beta2/INSTALL000066400000000000000000000166651337314105200175240ustar00rootroot00000000000000 INSTALLING OPENDKIM OVERVIEW ======== In order to install the opendkim as a milter to an MTA you will need to perform the following steps: * Compile the opendkim program itself. * Configure the opendkim for signing and/or verification. * Install the opendkim and configure your MTA to use it. Note that there is a difference between "OpenDKIM" and "opendkim". "OpenDKIM" is a package containing a library, a filter and some tools to be used in testing your DKIM installation. "opendkim" is the filter program contained in the "OpenDKIM" package. libopendkim is a library available as an API for programmers everywhere. That API is described in a set of HTML files in the OpenDKIM source code package. The opendkim filter program incorporates the libopendkim library and works with recent versions of sendmail and Postfix or any other MTA that supports "milter". For more information about milter, see . Sendmail is available at and Postfix is available at . OPTIONAL PACKAGES ================= OpenDKIM supports a few optional packages that can be included in the build to provide additional services. A few of these become mandatory when enabling certain features below. Specifying only the "--with-xxx" parameter to the "configure" command (described below) enables the package and makes a guess at where it might be installed on your system. If the configure script doesn't find it, you will need to specify the location with "--with-xxx=location". --with-db BerkeleyDB include file and library. If enabled without a specific path, the /usr/local/BerkeleyDB, /usr/local and /usr directories will be searched for both the required includes and the required libraries. Required for the following features: query_cache, stats --with-db-incdir --with-db-libdir --with-db-lib These provide a finer control over the location of BerkeleyDB include, library path and libary name where the default locations of --with-db are not enough. --with-domain Specifies the local domain name in use. Used only for generation of sample configuration files, etc. --with-gcov Compile with GNU code coverage enabled; the value provides the location of the gprof libraries if not in the default location. --with-gprof Compile with GNU profiling enabled; the value provides the location of the gprof libraries if not in the default location. --with-lcov Compile with Linux code coverage enabled; the value provides the location of the gprof libraries if not in the default location. --with-ldns Location of the "ldns" library, required for unbound. --with-libcurl Location of the curl library. Required for reputation query support. --with-libevent Location of the event library. Optional with unbound. --with-libgnutls Location of GNU's TLS includes and library. If not specified, "--with-openssl" is assumed. --with-libjansson Location of the jansson JSON library. Required for reputation query support, unless "--with-libxml2" is also specified. --with-libmemcached Location of the memcache library. Enables the "memcache" data set type. --with-libxml2 Location of the XML parser library. Optional for use with reputation query support. --with-lua Lua interpreter library. Enables fine-grained policy control via Lua script hooks, and also enables building of the "miltertest" test tool. --with-milter Sendmail's "milter" include file and library. Required unless compilation of the filter is disabled (see below). Enabled by default. --with-odbx Location of the OpenDBX installation on your system. Optional; enables use of a number of SQL and ODBC databases for configuration information. Version 1.3.7 or later is required. --with-openldap Location of the OpenLDAP installation on your system. --with-openssl Location of the OpenSSL installation on your system. Either this or libgcrypt required, and this one is assumed if libgcrypt is not enabled. If no specific location is provided, several common install locations will be searched for the required includes and libraries. --with-sasl Location of the Cyrus SASL include file definitions. This is used for authenticating against LDAP servers. --with-sql-backend Names the SQL backend in use on your system. The default is "mysql". See OpenDBX documentation for the list of valid values. --with-tre Location of the TRE installation on your system. This is required if you are using the "diffheaders" feature. If no specific location is provided, the /usr/local and /usr directories will be searched for the required includes and libraries. --with-unbound Location of the Unbound DNSSEC capable asynchronous resolver library and include file. FEATURES ======== There are several compile-time features you may select. Some of these are present but unsupported while others are fully-supported. Read the FEATURES file for a description of the unsupported features. The supported features are as follows. The can be turned on at compile time by adding "--enable-xxx" to the "configure" command line (described below), where "xxx" is the name of the feature. codecoverage Compile the code such that executing it produces code coverage and profiling output, used for code analysis. Not intended for production use. debug Produce debug-enabled libraries and executables. filter Compile the opendkim filter. Requires libmilter (see "--with-milter" above). This is on by default; if you don't want the filter, specify "--disable-filter". live-testing Enables unit tests that require live access to the Internet to succeed. popauth Enables support for POP-before-SMTP checks. query_cache Compile the opendkim library to support local caching of replies. (Requires libdb) rpath Include library paths in generated binaries. COMPILING ========= The opendkim filter requires either sendmail v8.13.0 or Postfix v2.3 or later for required milter protocol enhancements. To build this package you must first have installed or at least have available the OpenSSL package and libmilter. The former is available from or in package form from your vendor. At a minimum version 0.9.8 is required to meet DKIM requirements. The application library libmilter is part of the sendmail Open Source distribution and can be built and installed from there (ftp://ftp.sendmail.org). As Postfix currently does not provide milter library, you need to have sendmail sources or development package installed. See http://www.postfix.org/MILTER_README.html You can view the configuration options with the following command: ./configure --help The commands shown below assume a UNIX system with standard build tools installed. Steps to compiling the library and the milter: (1) Download the source from OpenDKIM (http://www.opendkim.org). (2) Unpack the tarball: tar -xzvf opendkim-.tar.gz Note: Use as the version number that you downloaded. (3) Change directories to the release directory (opendkim-) that was created in step 2. cd opendkim- (4) Run the "configure" script to configure the package for your operating system. ./configure (5) Compile the package. make (6) Install the output of the build. You probably need to become the superuser to run this step. make install CONFIGURING OPENDKIM ==================== The README document (in the opendkim directory) covers the installation and configuration of opendkim. OpenDKIM-rel-opendkim-2-11-0-Beta2/KNOWNBUGS000066400000000000000000000020141337314105200177520ustar00rootroot00000000000000 K N O W N B U G S I N O P E N D K I M The following are bugs or deficiencies in the OpenDKIM package that we are aware of but which have not been fixed in the current release. You probably want to get the most up to date version of this from http://www.opendkim.org. For descriptions of bugs that have been fixed, see the file RELEASE_NOTES. This list is not guaranteed to be complete. Check the OpenDKIM web site for additional pending bugs and feature requests. SIGNATURE HEADER TRUNCATION The sendmail MTA caps the length of headers to prevent a known MIME header attack. Unfortunately this can interfere with processing of a sufficiently large DKIM-Signature header. If you are getting failures on large signature headers which should otherwise be passing, consider adjusting the value of the MaxMimeHeaderLength option to a larger value (or to 0 which removes the limit). See the sendmail MTA configuration documentation for more information. $Revision: 1.1 $, Last updated $Date: 2009/07/16 18:42:55 $ OpenDKIM-rel-opendkim-2-11-0-Beta2/LICENSE000066400000000000000000000042761337314105200174730ustar00rootroot00000000000000Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of The Trusted Domain Project nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. Portions of this project are also covered by the Sendmail Open Source License, available in this distribution in the file "LICENSE.Sendmail". See the copyright notice(s) in each file to determine whether it is covered by either or both of the licenses. For example: Copyright (c) Sendmail, Inc. and its suppliers. All rights reserved. Files bearing the banner above are covered under the Sendmail Open Source License (see LICENSE.Sendmail). Copyright (c) , The Trusted Domain Project. All rights reserved. Files bearing the banner above are covered under the Trusted Domain Project License (above). Files bearing both banners are covered under both sets of license terms. THIS SOFTWARE IS PROVIDED BY THE TRUSTED DOMAIN PROJECT ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TRUSTED DOMAIN PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. OpenDKIM-rel-opendkim-2-11-0-Beta2/LICENSE.Sendmail000066400000000000000000000104371337314105200212220ustar00rootroot00000000000000 SENDMAIL OPEN SOURCE LICENSE The following license terms and conditions apply to this open source software ("Software"), unless a different license is obtained directly from Sendmail, Inc. ("Sendmail") located at 6475 Christie Ave, Suite 350, Emeryville, CA 94608, USA. Use, modification and redistribution (including distribution of any modified or derived work) of the Software in source and binary forms is permitted only if each of the following conditions of 1-6 are met: 1. Redistributions of the Software qualify as "freeware" or "open source software" under one of the following terms: (a) Redistributions are made at no charge beyond the reasonable cost of materials and delivery; or (b) Redistributions are accompanied by a copy of the modified Source Code (on an acceptable machine-readable medium) or by an irrevocable offer to provide a copy of the modified Source Code (on an acceptable machine-readable medium) for up to three years at the cost of materials and delivery. Such redistributions must allow further use, modification, and redistribution of the Source Code under substantially the same terms as this license. For the purposes of redistribution "Source Code" means the complete human-readable, compilable, linkable, and operational source code of the redistributed module(s) including all modifications. 2. Redistributions of the Software Source Code must retain the copyright notices as they appear in each Source Code file, these license terms and conditions, and the disclaimer/limitation of liability set forth in paragraph 6 below. Redistributions of the Software Source Code must also comply with the copyright notices and/or license terms and conditions imposed by contributors on embedded code. The contributors' license terms and conditions and/or copyright notices are contained in the Source Code distribution. 3. Redistributions of the Software in binary form must reproduce the Copyright Notice described below, these license terms and conditions, and the disclaimer/limitation of liability set forth in paragraph 6 below, in the documentation and/or other materials provided with the binary distribution. For the purposes of binary distribution, "Copyright Notice" refers to the following language: "Copyright (c) 1998-2009 Sendmail, Inc. All rights reserved." 4. Neither the name, trademark or logo of Sendmail, Inc. (including without limitation its subsidiaries or affiliates) or its contributors may be used to endorse or promote products, or software or services derived from this Software without specific prior written permission. The name "sendmail" is a registered trademark and service mark of Sendmail, Inc. 5. We reserve the right to cancel this license if you do not comply with the terms. This license is governed by California law and both of us agree that for any dispute arising out of or relating to this Software, that jurisdiction and venue is proper in San Francisco or Alameda counties. These license terms and conditions reflect the complete agreement for the license of the Software (which means this supercedes prior or contemporaneous agreements or representations). If any term or condition under this license is found to be invalid, the remaining terms and conditions still apply. 6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY SENDMAIL AND ITS CONTRIBUTORS "AS IS" WITHOUT WARRANTY OF ANY KIND AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. IN NO EVENT SHALL SENDMAIL OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING WITHOUT LIMITATION NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. $Revision: 1.1 $ $Date: 2009/07/16 18:43:18 $ OpenDKIM-rel-opendkim-2-11-0-Beta2/Makefile.am000066400000000000000000000041511337314105200205120ustar00rootroot00000000000000# Copyright (c) 2010-2014, The Trusted Domain Project. All rights reserved. AUTOMAKE_OPTIONS = foreign ACLOCAL_AMFLAGS = -I m4 SUBDIRS = SUBDIRS += libopendkim contrib docs if VBR SUBDIRS += libvbr endif if RBL SUBDIRS += librbl endif if LUA SUBDIRS += miltertest endif if STATS SUBDIRS += stats endif if REPUTE SUBDIRS += libut reputation endif if REPRRD SUBDIRS += reprrd endif if JANSSON SUBDIRS += autobuild endif SUBDIRS += opendkim dist_doc_DATA = FEATURES KNOWNBUGS LICENSE LICENSE.Sendmail \ RELEASE_NOTES.Sendmail dist_noinst_SCRIPTS = libtool DISTCLEANFILES = opendkim-@VERSION@.tar.gz # TODO: get configure.ac to generate --enable-{feature} for all # non-experimental features and substitute it here e.g @SUPPORTED_FEATURES@. # Perhaps all features would enable a more comprehensive test coverage map # though. DISTCHECK_CONFIGURE_FLAGS=--enable-vbr --with-lua --enable-stats --with-odbx --with-db --with-openssl=/usr/local --enable-atps --enable-replace_rules $(DIST_ARCHIVES): distcheck $(DIST_ARCHIVES).md5: $(DIST_ARCHIVES) md5 $? > $@ || md5sum $? > $@ $(DIST_ARCHIVES).sha1: $(DIST_ARCHIVES) sha1 $? > $@ || sha1sum $? > $@ $(DIST_ARCHIVES).asc: $(DIST_ARCHIVES) gpg -a -u security@opendkim.org --detach-sign $? push: $(DIST_ARCHIVES) $(DIST_ARCHIVES).sha1 $(DIST_ARCHIVES).md5 $(DIST_ARCHIVES).asc @echo "Are you sure you want to tag and release $(DIST_ARCHIVES)? (y/n)" @read confirm && [ $$confirm = 'y' ] git tag rel-opendkim-`echo $(VERSION) | sed 's/\./-/g'` git push --tags scp $(DIST_ARCHIVES) $(DIST_ARCHIVES).sha1 $(DIST_ARCHIVES).md5 $(DIST_ARCHIVES).asc RELEASE_NOTES cm-msk,opendkim@frs.sourceforge.net:/home/frs/project/o/op/opendkim/ dist-hook: [ -f $(distdir)/libopendkim/dkim.h ] && rm -f $(distdir)/libopendkim/dkim.h sed -e '/OPENDKIM_LIB_VERSION/s/0x[0-9]*/0x@HEX_VERSION@/' < $(srcdir)/libopendkim/dkim.h > $(distdir)/libopendkim/dkim.h echo "looking to see if @VERSION@ is in the RELEASE_NOTES" fgrep @VERSION@ $(srcdir)/RELEASE_NOTES sed -e 's|\(@VERSION@[ \t]*\)[0-9?]\{4\}\(/[0-9?]\{2\}\)\{2\}|\1'`date +%Y/%m/%d`'|' < $(srcdir)/RELEASE_NOTES > $(distdir)/RELEASE_NOTES .PHONY: push OpenDKIM-rel-opendkim-2-11-0-Beta2/ProjectGuide000066400000000000000000000243061337314105200207710ustar00rootroot00000000000000 OpenDKIM Release Planning MAJOR RELEASES: Major releases (i.e. for version x.y.z, those for which "x" increases) contain major new features or major code rewriting efforts. With very few exceptions, they are typically planned several months apart to allow for development complexity and extensive unit testing. They may be planned in conjunction with releases with other projects where the two are co-operating in some way. They should also include a beta period of at least a month. Heavy code review activity is expected. Users should anticipate the possibility of breakage if a binary replacement is done; though this will be avoided whenever practical, these releases are the ones where backward compatibility is most likely to be broken. Any change that establishes a new external dependency must occur in a major release. MINOR RELEASES: Minor releases (those for which "y" increases) contain new features or code changes not warranting a full major release. They are also typically planned a few months apart, though with more frequency than major releases. They generally coincide with conferences or other public events where the code or related topics may be featured, but this is not a scheduling requirement. They should always include a beta period of at least two weeks but preferably a month. Code review is required; anything not reviewed by release should be demoted to an FFR. An existing FFR can be activated, or a new one added, in a minor release. Backward compatibility with existing versions should be maintained whenever possible. No new external dependencies may be created. PATCH RELEASES: Patch releases (those for which only "z" increases) contain fixes to existing code only, and never contain new features or remove existing ones. A patch release is typically scheduled for two or three weeks after an important bug is reported, and any other bugs that occur during that window are generally included in that release. However, a patch release is never scheduled when doing so would collide with some other pending release. Beta periods are generally not required, though developers should plan to add unit tests to fixes where possible. Backward compatibility must be preserved in patch releases except where doing so is simply impossible. NOTES: - changes to anything in the "contrib" directory may appear in any release as they are unsupported OpenDKIM Source Code Management Policies 1) The source code management system in use is "git". There following branch structure is also in use: o Branch "master" always exists, and is the one to which all work is merged prior to doing a release. Only people doing the actual work of preparing releases should make any changes to this branch. All releases must also be tagged from a point on this branch with a name like "rel-opendkim-x-y-z" (consistent with the old CVS tag naming scheme). o Branch "develop" always exists, and is the one on which general development work takes place. It is open to all committers. In general, this branch has the following rules: - beta releases are made from this branch - bug fixes not requiring major code work can be done directly here - features ready for production use are merged to this branch from their specific development branches for automated testing and beta cycles - development of new features is NOT done here - major bug fixes are NOT done here o A release branch is only necessary when there are two active release lines in existence (e.g., when 2.0.x releases are still occurring while 2.1.0 development is in progress). In this case, "develop" represents the development of the new version while a release branch would sustain the older release line(s) until they are no longer needed. This means bug fixes merged to a release branch must also be merged to "develop". Release branches are named after the major and minor versions they cover, e.g. "release-2-0" for all 2.0.x releases. The procedure for this branch is the same as "develop" in that it is the destination for merges that should go into releases represented by that branch. These branches should be uncommon. o Bug fixes requiring more than trivial code changes must be done on a new branch whose name starts with "bug-" and is followed by the identity of the branch holder, another hyphen, and then some description of the work being done there; e.g. "bug-msk-sf1234567" (identifying a bug number) or "bug-msk-startup-crash" (short description). These are expected to be reviewed by at least one other person before being merged back to "develop". o Feature requests must be done on a new branch following a similar naming scheme except using a prefix of "feature-"; e.g. "feature-msk-dnssec" or "feature-msk-sf234567". These are also expected to get at least one reviewer before being merged back to "develop". o Experimental work branches are prefixed with "exp-" and otherwise follow the same naming convention. It is expected these branches will evolve into feature request or bug fix branches, or be abandoned. That transition does not require any review. 2) A patch releases does not require a beta period. They are, however, encouraged to be conducted, at least privately, and not last less than one week. A minor or major release requires a beta period of not less than a month, and there should be very little change activity within the final week of the beta period; if the last week contains several changes, the beta should be extended. 3) Active discussion of any non-trivial work being done on the opendkim-dev list is encouraged. 4) All developers are encouraged to keep an eye on what's going through the opendkim-cvs list for possible mistakes or other spontaneous review. 5) If you have questions about someone's design or choice of how to fix something, and especially if you have an idea about a more solid approach, feel free to bring it up on opendkim-dev. We're a community of experienced people, so peer review is important and encouraged. 6) Nothing, even small things, should go in to any release branch or the develop branch without being build-tested and run someplace first. 7) When making changes or improvements to libopendkim, write a unit test and add it to the system to cover your work. You can copy one of the existing ones and modify it accordingly. Any changes to libopendkim have to leave it with all unit tests still running. 8) Stick to the coding style (braces, tabs, comments, etc.). The code should look like it came from a coherent team; I shouldn't be able to tell where you patched something I wrote without using "git blame". 9) Anything you change should be documented in the RELEASE_NOTES file, following its current format. You don't need to document fixed typos or truly trivial things of that nature, but just about everything else should be mentioned. Remember to give credit where credit is due, though we generally don't attribute credit to people who are part of the project itself unless it's really a major contribution. 10) If you want a development sandbox, create a branch first (see below) and do your experimenting there. Commits to sandbox branches don't need to be reviewed by anyone. Sandboxes only get merged to release branches or the trunk after passing a review. 11) git commits on non-sandbox branches should describe what changed in enough detail to indicate to one of us why the change was made. We can see what changed using "git diff", so the "why" is important here. If you had any review done of your work, name the person(s) that did the review in your commit comment. 12) Nothing should cause compile-time warnings unless there's a really good reason not to clean them up. If that's the case, explain why the warnings should be tolerated in your commit comment. 13) Start your commit comment with "MFC:" (move from current) if the diff is a copy from the trunk, or with "MFB:" (move from branch) if it's a copy to the trunk, and name the other branch involved. 14) Where a commit references an open bug or feature request, specify such (e.g. "Fix bug #SF1234567" or "Feature request #SF2345678") as well as some descriptive text such as the problem being solved or the feature being added. The "SF" prefix is legacy from the times when there was more than one bug tracking system in use, but let's stick with it for now. Sandbox branching procedure: 1) Update your code to the point in git at which you want to branch 2) Update the BRANCHES file to contain your branch 3) Check in the BRANCHES file "git commit -m 'add branch XXX'" 4) "git tag base-exp--" (e.g. "git tag base-exp-dblack-async-dns") to lay down a reference tag, so that later you can produce a final diff of your work relative to the branch point. 5) "git branch exp--" to create the branch 6) Update your copy so it refers to the branch (e.g. "git checkout exp--"). 7) Code away! The same procedure applies for other types of branches. Production branch notes: 1) All branches should belong to a person (i.e. be named, like "bug-msk-...") unless they are release branches, in which case they are named after that code fork (e.g. "release-1-1" is for 1.1.x releases). Branches should be deleted only after they are either merged to develop or abandoned. 2) Whoever's doing releases (currently only msk) is responsible for all release branch creation and all merges to the master branch, and is also responsible for placing release tags during releases. 3) New features and dependencies only ever go on the develop branch, never on release branches. The exception to this is FFRs; new FFRs can go in on any release branch since they are off-by-default anyway, but still this should be avoided. FFRs only ever "go live", becoming production code, on the master branch. 4) Bug fixes relative to code that has already been released go on both the current release branch (if any) and the develop branch for later merge to the master. 5) When it's time for a new release line to begin (e.g. 2.1.x has been created but it's time to get some new features out so we need to start the 2.2.x releases), start a new release branch and do releases from there. If anyone has questions about anything above, feel free to ask about them before doing something that could cause a mess. OpenDKIM-rel-opendkim-2-11-0-Beta2/README000066400000000000000000000272301337314105200173410ustar00rootroot00000000000000OPENDKIM README =============== This directory has the latest open source DKIM filter software from The Trusted Domain Project. There is a web site at http://www.trusteddomain.org that is home for the latest updates. +--------------+ | INTRODUCTION | +--------------+ The Trusted Domain Project (TDP) is a non-profit corporation dedicated to research and development of techologies that promote trust in the use of domain names in on the Internet. The OpenDKIM Project is an initiative of TDP, and is primarily community effort to develop and maintain an open source library for producing DKIM-aware applications, and a "milter"-based filter for providing DKIM service. The DKIM sender authentication system was originally created by the E-mail Signing Technology Group (ESTG) and is now a draft standard of the IETF (RFC6376). DKIM is an amalgamation of the DomainKeys (DK) proposal by Yahoo!, Inc. and the Internet Identified Mail (IIM) proposal by Cisco. "milter" is a portmanteau of "mail filter" and refers to a protocol and API for communicating mail traffic information between MTAs and mail filtering plug-in applications. It was originally invented at Sendmail, Inc. but has also been adapted to other MTAs. The OpenDKIM project started as a code fork of version 2.8.3 of the open source "dkim-milter" package developed and maintained by Sendmail, Inc. The license used by The OpenDKIM project is found in the LICENSE file. Portions of this project are also covered by the Sendmail Open Source License, available in this distribution in the file "LICENSE.Sendmail". See the copyright notice(s) in each source file to determine whether or not it is covered by both licenses. This package consists of a library that implements the DKIM service and a milter-based filter application that can plug in to any milter-aware MTA to provide that service to sufficiently recent sendmail, Postfix or other MTAs that support the milter protocol. An optional asynchronous resolver library is also provided to work around limitations of the basic BIND resolver which comes installed on most systems. +--------------+ | DEPENDENCIES | +--------------+ To compile and operate, this package requires the following: o OpenSSL (http://www.openssl.org, or ask your software vendor for a package). Any version will get you started, however v0.9.8 or later is required if you want to be able to sign or verify messages using the SHA256 message digest algorithm which is generally required for current DKIM applications. OpenSSL 1.1.1 is required for ED25519 support. o sendmail v8.13.0 (or later), or Postfix 2.3, (or later) and libmilter. (These are only required if you are building the filter.) o Access to a working nameserver (required only for signature verification). o On Linux systems, either libbsd (BSD compatibility library) or some other library that provides strlcat() and strlcpy(). o If you wish to interface the filter with SQL databases, or store statistical information in a database, OpenDBX v1.3.7 or later is required. o If you wish to use the Lua interpreter hooks for filter policy control, or statistical extensions (--enable-statsext), Lua v5.1 or later is required. o If you wish to interface the filter with LDAP servers, OpenLDAP v2.1.3 or later is required. o For local hash or btree database support in either the filter or the library, Oracle's BerkeleyDB is required. All versions are supported. o If you are interested in tinkering with the build and packaging structure, you may need to upgrade to these versions of GNU's "autotools" components: autoconf (GNU Autoconf) 2.61 automake (GNU automake) 1.7 (or 1.9 to avoid warnings) ltmain.sh (GNU libtool) 2.2.6 (or 1.5.26 after make maintainer-clean) +-----------------------+ | RELATED DOCUMENTATION | +-----------------------+ The man page for opendkim (the actual filter program) is present in the opendkim directory of this source distribution. There is additional information in the INSTALL and FEATURES files, and in the README file in the opendkim directory. Changes are documented in the RELEASE_NOTES file. HTML-style documentation for libopendkim is available in libopendkim/docs in this source distribution. General information about DKIM can be found at http://www.dkim.org Mailing lists discussing and supporting the DKIM software found in this package are maintained via a list server at opendkim.org. Visit http://www.opendkim.org to subscribe or browse archives. The available lists are: opendkim-announce (moderated) Release announcements. opendkim-users General OpenDKIM user questions and answers. opendkim-dev Chatter among OpenDKIM developers. opendkim-cvs Automated source code change announcements. May be renamed soon to something more general since we're moving away from CVS. Bug tracking is done via the trackers on SourceForge at http://sourceforge.net/projects/opendkim. You can enter new bug reports there, but please check first for older bugs already open, or even already closed, before opening a new issue. +---------+ | WARNING | +---------+ Since OpenDKIM uses cryptography, the following information from OpenSSL applies to this package as well. PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG CRYPTOGRAPHY SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST COMMUNICATING TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS ILLEGAL IN SOME PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE TO YOUR COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL TECHNICAL SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR OTHER PEOPLE YOU ARE STRONGLY ADVISED TO PAY CLOSE ATTENTION TO ANY EXPORT/IMPORT AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHORS ARE NOT LIABLE FOR ANY VIOLATIONS YOU MAKE HERE. SO BE CAREFUL, IT IS YOUR RESPONSIBILITY. If you use OpenSSL then make sure you read their README file which contains information about patents etc. +---------------------+ | DIRECTORY STRUCTURE | +---------------------+ contrib A collection of user contributed scripts that may be useful. docs A collection of RFCs and drafts related to opendkim. libar An optional thread-safe asynchronous resolver library. libopendkim A library that implements the proposed DKIM standard. libopendkim/docs HTML documentation describing the API provided by libopendkim. libvbr An optional library that implements Vouch By Reference (VBR, RFC5518). opendkim A milter-based filter application which uses libopenkim (and optionally libar) to provide DKIM service via an MTA using the milter protocol. +----------------+ | RUNTIME ISSUES | +----------------+ WARNING: symbol 'X' not available The filter attempted to get some information from the MTA that the MTA did not provide. At various points in the interaction between the MTA and the filter, certain macros containing information about the job in progress or the connection being handled are passed from the MTA to the filter. In the case of sendmail, the names of the macros the MTA should pass to the filter are defined by the "Milter.macros" settings in sendmail.cf, e.g. "Milter.macros.connect", "Milter.macros.envfrom", etc. This message indicates that the filter needed the contents of macro X, but that macro was not passed down from the MTA. Typically the values needed by this filter are passed from the MTA if the sendmail.cf was generated by the usual m4 method. If you do not have those options defined in your sendmail.cf, make sure your M4 configuration files are current and rebuild your sendmail.cf to get appropriate lines added to your sendmail.cf, and then restart sendmail. MTA timeouts By default, the MTA is configured to wait up to ten seconds for a response from a filter before giving up. When querying remote nameservers for key and policy data, the DKIM filter may not get a response from the resolver within that time frame, and thus this MTA timeout will occur. This can cause messages to be rejected, temp-failed or delivered without verification, depending on the failure mode selected for the filter. When using the standard resolver library provided with your system, the DNS timeout cannot be adjusted. If you encounter this problem, you must increase the time the MTA waits for replies. See the documentation in the sendmail open source distribution (libmilter/README in particular) for instructions on changing these timeouts. When using the provided asynchronous resolver library, you can use the "-T" command line option to change the timeout so that it is shorter than the MTA timeout. d2i_PUBKEY_bio() failed After retrieving and decoding a public key to perform a message verification, the OpenSSL library attempted to make use of that key but failed. The known possible causes are: (a) Memory exhaustion (b) Key corruption If you're set to temp-fail messages in these cases, the remote end will probably retry the message. If the same message fails again later, the key is probably corrupted or otherwise invalid. You can try compiling with _FFR_LOG_SSL_ERRORS to have the filter extract OpenSSL library errors and include them in the system log when such conditions occur for further diagnostics. In one observed case, a corrupt key also caused the following to be logged: error:0D0680A8:asn1 encoding routines:ASN1_CHECK_TLEN:wrong tag; error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 error Other OpenDKIM issues: Report any bugs to the email address opendkim-users@lists.opendkim.org or to the sourceforge issue trackers accessible at: https://sourceforge.net/p/opendkim/_list/tickets +-----------------------------+ | Sendmail REWRITING FEATURES | +-----------------------------+ There are two features of the sendmail MTA which, if activated, can interfere with successful use of the DKIM service. The two features are MASQUERADE_AS and FEATURE(genericstable). See cf/README in the open source sendmail source code distribution for more information. Due to the way the milter protocol is incorporated into the MTA, opendkim sees the headers before they are modified as required by those two features. This means the DKIM signature is generated based on the headers originally injected by the mail client and not on the headers which are actually sent out by the MTA. As a result, the verifying agent at the receiver's side will be unable to verify the signature as the signed data and the received data don't match. The suggested solutions to this problem are: (1) Send mail with the headers already written as needed, obviating the need for these features (or just turn them off). (2) Have two MTAs set up, either on separate boxes or on the same box. The first MTA should do all of the rewriting (i.e. use these two features) and the second one should use opendkim to add the signature and do no rewriting at all. (3) Have multiple DaemonPortOptions lines in your configuration file. The first daemon port (port 25) does the header rewriting and then routes the message to the second port; the latter does no rewriting but does the signing and then sends the message on its way. There is also a feature of Sendmail that will cause it to alter addresses after signing but before they are transmitted. The feature, which is on by default, passes addresses in header fields to the resolver functions to ensure they are canonical. This can result in the replacement of those strings in the sent message with their canonical forms only after the message is signed, which will invalidate the signatures. To suppress this feature, add the following line to your sendmail.mc and submit.mc configuration files, re-generate your configuration and restart the filter: FEATURE(`nocanonify') -- Copyright (c) 2010-2012, 2014, 2018, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/README.ERLANG000066400000000000000000000131501337314105200203040ustar00rootroot00000000000000OPENDKIM ERLANG NOTES ===================== This document explains how to use Erlang datasets in the OpenDKIM configuration. There are two lookups for which an Erlang dataset may be used. The SigningTable lookup uses a signing pattern based on the message sender to perform a lookup, returning an arbitrary "label" which is an unique identifier (a string or number) associated to the pattern. The KeyTable lookup uses this label in its search, expecting the three fields of data below to be returned, in order: domain name, selector, private key (in ASCII armor, or a filename) An OpenDKIM configuration that makes use of distributed Erlang can be specified in the following manner. SigningTable erlang:NODE@HOST:COOKIE:MODULE:KEY_LOOKUP_FUNCTION KeyTable erlang:NODE@HOST:COOKIE:MODULE:DATA_LOOKUP_FUNCTION The strings NODE, HOST, COOKIE, MODULE are used to set up a connection to a distributed Erlang node. Multiple nodes must be specified, separated by commas. In that case, OpenDKIM will try to connect to each of them in order, stopping when a successful connection is established or when no more nodes are available. Note that the cookie may not contain the colon (':') character. Once the connection is established, it will call the function MODULE:KEY_LOOKUP_FUNCTION/1, giving it the signing pattern mentioned above as an argument. The result from this call will be used as an argument to MODULE:DATA_LOOKUP_FUNCTION/1, which is supposed to return the three pieces of data previously described. The erlang datasets are walkable, and therefore the function given as the KeyTable must be able to return the "next" entry for the database. OpenDKIM signals this to the function by passing the atom 'first' as its argument when the first entry of the database is expected to be returned, or the tuple {'next', PreviousKey} when the next entry is supposed to be returned. A complete example is given below. It assumes that the OpenDKIM dataset will be stored in a Mnesia database. Mnesia database and table creation is not covered by these notes. -module(dkim). -export([find_id/1, find_domain/1). % % This module implements the OpenDKIM Erlang dataset API. A Mnesia database % storing DKIM information for domains is assumed. % -include_lib("stdlib/include/qlc.hrl"). % This example uses the domain itself as the domain ID. This is simpler, and as % OpenDKIM will always send the ID as a bitstring, it avoids the need for type % conversions on the Erlang side. -record(dkim, { domain :: binary(), selector :: binary(), public_key :: binary(), private_key :: binary() }). % % SigningTable function: this function will be called on pattern lookups, % and must respect the type specification given below (i.e., it must return % the tuple {ok, ID} on success or the atom 'not_found' otherwise. The lookup % pattern is always given as a bitstring. In this example, the function just % checks if the domain is in the database, returning the domain name itself % as the domain ID. % -spec find_id(binary()) -> {ok, binary()} | not_found. find_id(Domain) when is_binary(Domain) -> mnesia:transaction(fun() -> TH = mnesia:table(dkim, [{lock, read}]), case qlc:e(qlc:q([DKIM || DKIM <- TH, DKIM#dkim.domain =:= Domain])) of [] -> not_found; _ -> {ok, Domain} % Return the domain ID (here, the domain itself). end end). % % KeyTable function: this function will be called on ID lookups, where an ID % is the unique domain identifier returned by dkim:find_id/1. The type % specification is given below. IDs are always given as bitstrings, even if % they're stored in the database as integers. Therefore, if you use integer % IDs you must convert the argument to the correct type by yourself. % % The function must support "walking" the database, returning the next % record on each call. When database walking is initiated the atom 'first' % will be given as an argument. Further records will be retrieved by passing % a {next, PreviousKey} tuple as the argument to the function. % -type dkim_data() :: {binary(), binary(), binary()}. -type dkim_data_with_id() :: {binary(), binary(), binary(), binary()}. -spec find_domain (first | {next, binary()}) -> {ok, dkim_data_with_id()} | '$end_of_table' ; (binary()) -> {ok, dkim_data()} | not_found. find_domain(first) -> mnesia:transaction(fun() -> case mnesia:first(dkim) of '$end_of_table' -> '$end_of_table'; Domain -> {ok, {Domain, Selector, PrivKey}} = find_domain(Domain), % OpenDKIM expects the domain ID, domain name, selector and private % key, in this order. Since the domain name is also its ID in this % example, it is returned both in the first and second tuple fields % below. {ok, {Domain, Domain, Selector, PrivKey}} end end); find_domain({next, Domain}) when is_binary(Domain) -> mnesia:transaction(fun() -> case mnesia:next(dkim, DomainId) of '$end_of_table' -> '$end_of_table'; NextDomain -> {ok, {NextDomain, Selector, PrivKey}} = find_domain(NextDomain), % Return the next domain ID in the database, and the three required % dataset fields. As above, the domain name is used as its ID. {ok, {NextDomain, NextDomain, Selector, PrivKey}} end end); find_domain(Domain) when is_binary(Domain) -> mnesia:transaction(fun() -> TH = mnesia:table(quota, [{lock, read}]), case qlc:e(qlc:q([D || D <- TH, D#dkim.domain =:= Domain])) of [] -> not_found; [#dkim{domain = Domain, selector = Selector, private_key = PrivKey}] -> % Return the three required dataset fields. {ok, {Domain, Selector, PrivKey}} end end). OpenDKIM-rel-opendkim-2-11-0-Beta2/RELEASE_NOTES000066400000000000000000002354611337314105200204430ustar00rootroot00000000000000 OPENDKIM RELEASE NOTES This listing shows the versions of the OpenDKIM package, the date of release, and a summary of the changes in that release. 2.11.0 2018/11/?? Add support for ED25519 keys. GNUTLS support provided by Dilyan Palauzov. Add "header.s" and "header.a" in generated Authentication-Results header fields. Add _FFR_CONDITIONAL, experimental support for conditional DKIM signatures. Make odkim.internal_ip() available to all Lua hooks. Problem noted by Iosif Fettich. Make bind code DNSSEC-aware. Patch from Jack Bates. Fix dkimf_db_nextpunct() so it doesn't incorrectly identify an encoded hex digit as a value delimiter. Fix issue #8: The password file critical section isn't big enough. Patch from Dilyan Palauzov. Fix issue #9: Plug a few failure mode memory leaks. Patch from Dilyan Palauzov. Fix issue #15: Don't automatically skip the body when one mode (sign or verify) doesn't need it, because the other one might. Patch from Dilyan Palauzov. Fix issue #28: RequiredHeaders should report and log the specific error and reject the message, as documented. Patch from Dilyan Palauzov. Fix bug #234: Make "NoHeaderB" do something. Reported by Joseph Coffland. Fix bug #235: Quote "header.b" values in case they contain a slash (which must be quoted). Fix bug #237: Fix processing of "SoftStart". CONFIG: Add compatibility with openssl-1.1.0. Patch from Scott Kitterman. CONTRIB: Simplfy some logic in contrib/repute. Patch from Dilyan Palauzov. LIBOPENDKIM: Feature request #190: Reject signature object requests where the domain name or selector includes non-printable characters. Suggested by Franck Martin. LIBOPENDKIM: Re-fix bug #226: Deal with header fields that are wrapped before there's any content. Somehow the wrong fix was committed. Originally reported by Alessandro Vesely; re-reported by David Stevenson. LIBOPENDKIM: Fix bug #233: In the weird case of duplicate signatures, constrain the size of the resulting "header.b" value. Problem noted by Joseph Coffland. LIBOPENDKIM: Fix bug #270: Don't set an upper bound on the size of the canonicalization buffer, which interferes with processing oversized input lines. Reported by Mars Peng. TOOLS: Feature requrest #187: Add option to match subdomains when generating zone files. Patch from Andreas Schulze. 2.10.3 2015/05/12 LIBOPENDKIM: Make strict header checking non-destructive. The last change to this code resulted in failing signatures. Reported by Pedro Morales and Wez Furlong. 2.10.2 2015/05/10 Fix bug #221: Report a DKIM result of "policy" if MinimumKeyBits or UnprotectedKey cause the signature to result in a "pass" override. Reported by Kurt Roeckx. Fix bug #227: Revert removal of SenderHeaders configuration setting. Document that it is now limited to signature selection. LIBOPENDKIM: Fix bug #226: Deal with header fields that are wrapped before there's any content. Reported by Alessandro Vesely. CONTRIB: Update to contrib/systemd/opendkim.service.in from Steve Jenkins. 2.10.1 2015/02/03 Fix bug #214: Handle arbitrarily large From: fields. Reported by Tomohiko Sasaki. Fix bug #220: Make DB_SIGNINGTABLE symbol available in Lua scripts. Problem noted by Klaus Heinrich. LIBOPENDKIM: Fix bug #213: Remove "dkim_default_senderhdrs" from dkim.h. Problem noted by Daniel J. Luke. LIBOPENDKIM: Fix bug #219: Unresolved CNAMEs are not failures, according to the DNS (see RFC6604), so report them as NXDOMAIN or similar. Reported by Alessandro Vesely. 2.10.0 2014/12/27 Feature request #182: Remove "AddAllSignatureResults". All signature results will now be added via Authentication-Results header fields. Requested by Tomki Camp. Feature request #180: Rename "LDAPSoftStart" to "SoftStart" and apply it to SQL connections as well. Requested by Daniel Kauffman. Feature request #179: Add "IgnoreMalformedMail" option. Fix bug #183: Discontinue support for ADSP. This removes the following configuration file items: AddAllSignatureResults LocalADSP ADSPAction NoDiscardableMailTo ADSPNoSuchDomain On-PolicyError BogusPolicy SendADSPReports DisableADSP SenderHeaders LDAPSoftStart UnprotectedPolicy Make "rrvs" and "smime" recognized Authentication-Results methods. LIBOPENDKIM: Feature request #157: Add dkim_mail_parse_multi(). Suggested by Alessandro Vesely. LIBOPENDKIM: Feature request #185: Add dkim_set_dnssec(). Patch from Alec Peterson. LIBOPENDKIM: Fix bug #183: Discontinue support for ADSP. This means all of the following: - the dkim_policy_t type has been removed - the DKIM_POLICY_* constants have been removed - the DKIM_PRESULT_* constants have been removed - passing DKIM_OPTS_SENDERHDRS to dkim_options() now results in an error - the DKIM_PSTATE structure has been removed - all of the following functions have been removed: dkim_policy(), dkim_policy_dnssec(), dkim_policy_getqueries(), dkim_policy_getreportinfo(), dkim_policy_state_free(), dkim_policy_state_new(), dkim_policy_syntax(), dkim_getpolicystr(), dkim_getpresult(), dkim_getpresultstr(), dkim_set_policy_lookup(), dkim_test_adsp() LIBOPENDKIM: DKIM_LIBFLAGS_STRICTHDRS now also confirms syntactical validity of the From field before proceeding with a signing or verifying operation. Suggested by Wez Furlong. CONTRIB: Fix bug #207: Clean up the "stats" directory. CONTRIB: Add "repute" directory which could eventually replace the PHP implementation. Submitted by Daniel Black. CONTRIB: Patches to systemd and init/redhat from Steve Jenkins. 2.9.3 2014/12/27 Fix bug #177: Plug leaking "result" structures when OpenLDAP is in use. Truncate configuration file lines at carriage return. Replace overlapping strlcpy() with memmove() in dkim_get_key_file(). Reported by Daniel J. Luke. Patch #32: Re-arrange the execution logic to drop privileges in proper order. LIBOPENDKIM: dkim_header() is now a lot more strict about the input it will accept (see RFC5322 Section 2.2). LIBOPENDKIM: Tighten relaxed modes to break on only DKIM-defined whitespace characters. Problem noted by Elizabeth Zwicky. LIBOPENDKIM: Fix bug #208: If a signature fails to verify for either reason (header hash mismatched or body hash mismatched), set DKIM_SIGERROR_BADSIG so that Authentication-Results doesn't report a failure with "no signature error". TOOLS: Feature request #178: Add "-F" flag to opendkim-genzone so records are created with the FQDN. Patch from Andreas Schulze. REPUTATION: Handle parameters safely in repute.php. Reported by Daniel Black. 2.9.2 2014/04/02 Fix some conflicting unit tests. Reported by Eray Aslan. BUILD: Fix bug #195 part II: Compile all binaries with pthreads support as needed by libopendkim features. Reported by Walter Haidinger. BUILD: Fix packaging damage with autobuild. Reported by Andreas Schulze. 2.9.1 2014/03/15 Feature request #177: Add "LuaOnlySigning" so that only the Lua setup script makes signing requests; suppresses automatic application of the signing table. Requested by Daniele Orlandi. Fix bug #185: odkim.signfor() wasn't processing its arguments properly. Reported by Daniele Orlandi. Fix bug #199: Fix use of uninitialized buffer when generating SMTP response strings due to ADSP rejections. Problem noted by Ache. Fix infinite loop when mlfi_connect() is called with a hostname starting with a "." character. Reported by Philip Guenther. Fix loading of refiles when trailing spaces are present in the value. Problem noted by Amal Francis. LIBOPENDKIM: Only call dkiml_dns_close() if there was a dkiml_dns_service handle set by dkiml_dns_init(). Also, when closing, reset that handle to NULL. LIBOPENDKIM: The various dkim_dns_set_*() functions, when passed a NULL function pointer, merely store it, making the corresponding function a no-op. Previously, doing so restored the default. LIBOPENDKIM: Have dkim_sig_getreportinfo() return descriptors (if available) regardless of the signer's reporting parameters. Problem noted by Wez Furlong. BUILD: Fix bug #188: Clean up last remnants of libstrl. BUILD: Fix bug #190: Check for HAVE_SUN_LEN in opendkim-db.c. Problem noted by Patrick Laimbock. BUILD: Fix bug #191: Better minimum version checks for libmemcached. Problem noted by Patrick Laimbock. BUILD: Fix bug #192: Different test for libevent, from Patrick Laimbock. BUILD: Fix bug #193: Don't throw away user-provided compilation variables. Problem noted by Quanah Gibson-Mount. BUILD: Fix bug #195: Compile opendkim-genzone with pthreads support. Reported by Walter Haidinger. BUILD: Fix bug #202: Fix pkg-config check for GNUTLS. Reported by Dilian Wesselinov Palauzov. BUILD: Fix bug #203: opendkim-genzone requires pthreads. BUILD: Patch #29: Look for libmilter in lib64. Patch from Dilian Wesselinov Palauzov. BUILD: Patch #30: Include libdl when linking in Lua. Patch from Dilian Wesselinov Palauzov. BUILD: Don't throw away user-provided compilation variables. Problem noted by Quanah Gibson-Mount. BUILD: Rename "--with-mdb" to "--with-lmdb" for consistency with that package's naming conventions. CONTRIB: Fix bug #184: Update to contrib/systemd/opendkim.service from Steve Jenkins. MILTERTEST: Add "polite" flag to mt_disconnect(). TOOLS: Fix bug #187: Increase buffer size for the private key in opendkim-testkey. Problem noted by Andreas Schulze. TOOLS: Fix opendkim-spam to match the schema found in stats/mkdb.mysql. Problem noted by Benny Pedersen. 2.9.0 2013/12/09 NOTE: During the development cycle for this release, SourceForge changed their bug numbering system. Bug numbers are recorded here as they were generated by the current system at the time they were filed. The older ones (prefixed "SF") have since been renumbered or may no longer be in the system. Feature request #169: Discontinue libxml2 support in the reputation code. Feature request #174: Drop internal libstrl implementation. Feature request #175: Discontinue support for libdkimrep. Feature request #176: Update to the final REPUTE RFCs. Activate _FFR_REDIRECT. Fix bug #178: Add support for "dmarc" as an authentication method (though it hasn't been formally registered yet) and fix a minor Authentication-Results parsing problem. Problem noted by Martin Kauchler. Fix bug #179: Correct handling of SignatureTTL. Problem noted by Kyle Cummings. Fix bug #180: Drain results object when doing a DB walk of a postgresql table. Problem noted by Szucs Adam. Fix bug #182: Add an Authentication-Results header field even for messages with no valid From: field or a fatal structural violation. Reported by John Wood. Teach dkimf_db_walk() about LDAP soft starting, and don't escape the forced "*" when walking. Also handle incorrect attribute counts without causing an assertion failure. Problem noted by Andreas Schulze. Call dkimf_config_free() on shutdown so that all DBs get properly closed and everything gets deallocated. LIBOPENDKIM: Fix bug #168: Report an unresolved CNAME for ADSP records as simply absent. Suggested by Eugene Crosser. LIBOPENDKIM: Add DKIM_LIBFLAGS_REQUESTREPORTS to request that an "r=y" tag be added to signatures, per RFC6651. TOOLS: Fix boundary condition in opendkim-testmsg. Reported by Wez Furlong. DOCS: Feature request #168: Improve documentation of signature verification failure debugging features. DOCS: Feature request #172: Describe socket selection procedure in detail, and mention selinux command to get set up. Suggested by Kevin San Diego. 2.8.4 2013/07/15 Fix bug #169: Add "::1" to the default InternalHosts list. Suggested by Norbert Aschendorff. Fix bug #171: Escape "+" character in regex generation. Reported by Scott Kitterman. Fix bug #172: Repair broken AutoRestartRate logic. Patch from Sho Kubata. Fix bug #SF3603525: Discard duplicate results from non-DKIM methods. Problem noted by John Wood. Fix bug #SF3611976: Fix up quarantine option handling. Problem noted by Claus Assmann. TOOLS: Fix bug #SF3609716: Fix meaning of "-S" in opendkim-genkey. Problem noted by Quanah Gibson-Mount. BUILD: Fix bug #SF3612816: Build compatibility with Lua 5.2. Patch from Hirohisa Yamaguchi. 2.8.3 2013/05/04 Log something when refusing to sign because the private key was too small. This also adds a new "On-SignatureError" handler setting, and a new status code DKIM_STAT_SIGGEN. Problem noted by Jim Fenton. Fix application of "On-InternalError" setting. Problem noted by Claus Assmann. Feature request #SF3609496: Don't apply reputation checks to internal clients. 2.8.2 2013/03/27 Authentication-Results tokens should be checked without case sensitivity. Problem noted by Chris Meidinger. Fix snprintf() arguments in dkimf_checkfsnode(). Problem noted by Scott Kitterman. CONTRIB: Patch #SF3608716: Fixes to spec/opendkim.spec.in from Kouhei Sutou. 2.8.1 2013/03/19 Fix bug #SF3607071: Report the reason why a key file is determined to be unsafe. Problem noted by Doug Barton. Fix bug #SF3607072: When checking for key file safety, take any "-u" value provided on the command line into account. Problem noted by Doug Barton. Fix bug #SF3608401: Solaris 10 doesn't have strsep(). Problem noted by Bryan Costales. BUILD: Fix build for versions of libdb between 3.1 and 4.6. Problem noted by John Wood. 2.8.0 2013/02/25 Feature request #SF2964383: Add DKIM_LIBFLAGS_STRICTRESIGN, which inhibits signing of a handle tagged for resigning when the attached verifying handle had no valid signatures in it. Feature request #SF3155117: Do a more thorough check for writeable key files, checking more of the filesystem permission tree. Feature request #SF3530734: Add "LDAPDisableCache", which suppresses the creation of a local cache in front of LDAP queries. Requested by Quanah Gibson-Mount. Feature request #SF3547359: If compiled with libcurl, add "SMTPURI" configuration option that allows direct SMTP transmission failure reports. Requested by Andreas Schulze. Feature request #SF3578197: Allow per-message override of the list of header fields to be signed. Requested by Alec Peterson. Feature request #SF3590860: Combine collected reputation values into an overall allowed rate under _FFR_REPRRD, as is done for the other reputation code. Feature request #SF3598991: Add odkim.signfor() function to the Lua setup script. Requested by Marcin Owsiany. Feature request #SF3599409: Modify dkimf_checkip() to try surrounding the IP address part of every query with square brackets, which is a common way to do IP address literals in email contexts. Requested by Quanah Gibson-Mount. Fix bug #SF3531477: Add (hopefully temporary) configuration option "DisableCryptoInit" so that opendkim's initialization of the crypto library doesn't conflict with the same work done by other libraries. Reported by Quanah Gibson-Mount. Fix bug #SF3599901: Rename "InsecureKey" to "UnprotectedKey" and "InsecurePolicy" to "UnprotectedPolicy", as the term "insecure" in reference to a key is sometimes interpreted to mean "not enough random bits" rather than as a keyword describing the presence or absence of DNSSEC protection. What's logged in Authentication-Results header fields has been similarly modified. Suggested by Scott Kitterman. Fix bug #SF3604525: Don't divide by zero when the query cache hasn't been used. Reported by Denis Klimov. Protect against handling of signatures with empty domains, which could cause a NULL dereference and a crash. Problem noted by Motohiro Ishiyama and John Wood. Do ATPS checks when enabled even if ADSP is disabled. Don't fail to start on empty or null configuration files. Problem noted by Steve Jenkins. Patch #SF3593422: Update for MDB 0.9.5 support. Patch from Quanah Gibson-Mount. LIBOPENDKIM: Fix header canonicalization when DKIM_LIBFLAG_FIXCRLF is used in combination with dkim_chunk(). Problem noted by Dave Kelly and Heather Lord. LIBOPENDKIM: Enable dkim_getcachestats() and the underlying function to extract the current number of keys in the cache, and also provide a counter reset mechanism. BUILD: Feature request #SF3547151: Check for Lua package name variants in use on Debian. Requested by Scott Kitterman. BUILD: Feature request #SF3599902: Change OpenSSL existence test to help with Debian packaging. Requested by Scott Kitterman. BUILD: Add "--with-test-socket" to force all of the filter unit tests to use a specific socket. Based on a bug report from Scott Kitterman. BUILD: Add checks for strlcat()/strlcpy() in libbsd. Patch from Scott Kitterman. CONTRIB: Fix bug #SF3575666: Pass pid file path to killproc. Suggested by Christophe Wolfhugel. CONTRIB: Add systemd directory. Contributed by Steve Jenkins. CONTRIB: Split out initial key generation function from contrib/init/redhat/opendkim. Contributed by Steve Jenkins. MILTERTEST: Don't crash in mt_connect() if the socketspec doesn't contain a colon. MILTERTEST: When connect() fails for an AF_INET socket, it apparently leaves the socket unusable. Discard the socket when that happens and get a new one. MILTERTEST: Add a way to extend the mt.connect() retry interval via environment variables so a large test suite can be easily extended on slow systems. Problem noted by Scott Kitterman. TOOLS: Register DNS functions before calling dkim_dns_init() in opendkim-testkey. Problem noted by Jeff Anton. TOOLS: Add "-K" (keep temporary files) flag for opendkim-testmsg. 2.7.4 2013/01/06 Fix bug #SF3596147: Allow arbitrarily long configuration file lines. Based on a patch from Daniel Black. Fix bug #SF3596229: Fix logging of signature errors, which logged the domain name twice instead of the domain name and the selector. Patch from Daniel Black. Safely handle incoming Authentication-Results fields with large number of tokens. Problem noted by Motohiro Ishiyama and John Wood. Avoid mixing up status codes when processing conf_logresults, leading to confusing log entries. Problem reported by John Wood. Fix ADSP logging. Problem noted by Claus Assmann. 2.7.3 2012/11/29 Log DB error string in dkimf_add_signrequest(), and fix a DSN handling error in dkimf_db_strerror(). Problem noted by Simone Caruso. LIBOPENDKIM: Ignore entries in the oversign header field name list that are empty, and an oversign header field name list that is present but empty. Problem noted by Alec Peterson. LIBOPENDKIM: Allow header field lists to be empty, flushing any that were previously defined. Problem noted by Alec Peterson. BUILD: Improve tests for including . Based on a patch from Eray Aslan. REPUTATION: Use lowercase for keywords in REPUTE query generation and handling. STATS: Clean up a dead link in opendkim-genstats. Patch from Andreas Schulze. 2.7.2 2012/11/14 Log the author domain name when rejecting or discarding due to ADSP. LIBOPENDKIM: Improve re-entrancy of dkim_eoh() when verifying. Requested by Alec Peterson. LIBOPENDKIM: Only do a single read attempt of a private key under GNUTLS to avoid hiding a useful error code. Problem noted by Alec Peterson. STATS: Add long option support for opendkim-importstats. Based on a patch from Christian Roessner. STATS: Fix overly-strict domain name rules in opendkim-reportstats. Reported by Christian Roessner. TOOLS: Fix opendkim-genkey subdomains default. Problem noted by Quanah Gibson-Mount. TOOLS: Fix opendkim-testmsg GNUTLS initialization. Problem noted by Alec Peterson. TOOLS: Add ability to assert a reporter ID to opendkim-spam. Based on a patch from Christian Roessner. TOOLS: Add ability to skip a fixed number of Received: fields. Problem noted by Christian Roessner. TOOLS: Print a warning when asked to generate a key smaller than the recommended minimum. BUILD: Fix bug #SF3585163: Use a provided libstrl if detected. Based on a patch from Eray Aslan. BUILD: Portability fixes for Solaris 10 from Claus Assmann and Leena Heino. 2.7.1 2012/10/30 Fix bug #SF3581657: Fix faulty logic in LDAP open code. Problem noted by Quanah Gibson-Mount. Fix bug #SF3581743: Properly handle NULLs returned from OpenDBX queries and low field counts in dkimf_db_walk(). Problem noted by Adam M. Jacques. In the _FFR_REPUTATION code, free JSON objects when done with them. TOOLS: Fix argument parsing in new version of opendkim-genkey. Problem noted by Steve Jenkins. 2.7.0 2012/10/24 Feature request #SF2964375: Reject configuration files that have a SigningTable referencing a missing or malformed KeyTable entry. Feature request #SF3544764: Support for libar has been discontinued. For asynchronous and/or thread-safe resolver service, use libunbound or a suitable version of BIND. Feature request #SF3545658: Replace "ResolvConf" with "Nameservers" and add support for NS list overrides for versions of bind that have res_setservers(). Also rename "UnboundConfigFile" to "ResolverConfiguration", and make "TrustAnchorFile" generally available. Feature request #SF3547124: Skip reputation checks on passing signatures whose keys had a "t=y" value. Feature request #SF3555842: Add "ReputationTest" setting. Requested by Andreas Schulze. Feature request #SF3556439: Update opendkim-atpszone per RFC6541. Feature request #SF3559744: Add library option DKIM_OPTS_MINKEYBITS allowing one to specify a minimum number of key bits for acceptable keys and signatures. This is exposed through new configuration file option "MinimumKeyBits". The default is 1024. Fix bug #SF3536414: Activate _FFR_OVERSIGN, and remove DKIM_OPTS_ALWAYSHDRS. Fix bug #SF3536655: Rename "X-Header" to "SoftwareHeader", and rename all header fields added that start "X-" to remove that prefix, per RFC6648. The old name will be accepted through the end of the 2.7.x line. Fix bug #SF3538896: Remove antiquated CVS Id: tags, which cleans up some (harmless) build warnings. Suggested by Andreas Schulze. Fix bug #SF3548741: Add "ReputationTimeout" for use inside _FFR_REPUTATION, rather than using the built-in default or a hard-coded one. Fix bug #SF3549307: Remove _FFR_REPUTATION_CACHE, as it is redundant to caching code that's part of _FFR_REPUTATION already. Fix bug #SF3555844: Get repute client code in sync with repute.php (and the current REPUTE WG drafts). Problem noted by Andreas Schulze. Fix bounds checking in the dstring printf functions. Fix loop structure in the C side of odkim.get_rcpt(). Problem noted by Todd Lyons. Change all temporary directory defaults from /var/tmp to /tmp. Activate _FFR_LUA_GLOBALS. Request the milter permissions required to get _FFR_REDIRECT working. Patch from Andreas Schulze. Add _FFR_REPRRD, which is a second approach to DKIM-based reputation using round robin databases and Holt-Winters foreacasting using rrdtool (see http://oss.oetiker.ch/rrdtool/). Still experimental. Patch #SF3555843: With sufficient verbosity, report the default configuration file path. Patch from Andreas Schulze. BUILD: Fix bug #SF3531658: Move the strlcat() and strlcpy() implementations to their own library so that programs don't drag in crypto and other dependencies they don't need. Also clean up several other unnecessary dependencies imposed by imprecise use of autoconf. Problem noted by Andreas Schulze. BUILD: Patch #SF3555845: Add support for older versions of libcurl. Based on a patch by Andreas Schulze. BUILD: Install non-user things in sbin instead of bin. Suggested by Andreas Schulze. LIBOPENDKIM: Feature request #SF3565006: Add dkim_add_querymethod() and dkim_sig_seterror(), define DKIM_CBSTAT_DEFAULT, and remove an assertion in dkim_get_key_dns(), which together allow for applications to develop non-standard key retrieval mechanisms. Suggestion and patches from Ken Murchison. LIBOPENDKIM: Fix bug #SF3559080: Log correct domains and selectors with SSL errors. LIBOPENDKIM: Add DNS functions dkim_dns_config(), dkim_dns_init(), dkim_dns_nslist(), dkim_dns_set_init(), dkim_dns_set_close(), dkim_dns_set_nslist(), dkim_dns_set_config(), dkim_dns_set_trustanchor(), dkim_dns_trustanchor(). LIBOPENDKIM: Patch #SF3562496: Add DKIM_OPTS_REQUIREDHDRS to allow alteration of the mandatory header field set. Patch from Ken Murchison. LIBOPENDKIM: If "q=" is present and method "dns" is specified, it must be followed by "/txt", per RFC6376. LIBOPENDKIM: For dkim_add_xtag(), copy the provided values so the caller doesn't have to keep them around. LIBOPENDKIM: Allow dual signing of a single body with dkim_resign(). Suggested by Ken Murchison. STATS: Fix bug #SF3555847: Add "--nocircles" to opendkim-gengraphs to allow operation with versions of gnuplot that don't know what "with circles" means. Problem noted by Andreas Schulze. STATS: Patch #SF3555841: Temporary table SQL correction. Patch from Andreas Schulze. TOOLS: Feature request #SF3553918: Add "-u" flag to opendkim-atpszone and opendkim-genzone enabling them to produce output suitable for use as input to nsupdate(8). Based on a suggestion by Dave Crocker. TOOLS: Feature request #SF3558818: Teach opendkim-testkey about the new "ResolverConfiguration" setting. Based on a problem report from Patrick Ben Koetter. TOOLS: Fix bug #SF3565013: Replace opendkim-genkey with a perl script that knows how to do splitting of character-strings in DNS TXT records. Problem reported by Todd Lyons. TOOLS: Fix bug #SF3568846: Add "-t" to opendkim-testmsg to allow override of the directory where temporary files go. Also, clean up temporary files after creating them. TOOLS: Add opendkim-rephistory. 2.6.7 2012/07/23 Fix input handling for file data sets for the macro case. Problem noted by Allan Wind. Ensure NULL-termination of macro value tests. STATS: Fix hang bug in opendkim-reportstats. Problem noted by Todd Lyons. STATS: Fix bug #SF3547363: Fix "Top 10" and DNSSEC trend reports. Problem noted by Andreas Schulze. 2.6.6 2012/07/18 LIBAR: Fix bug #SF3544522: Not all systems define a "_len" member for the sockaddr structures. Reported by Stevan Bajic. LIBOPENDKIM: Fix bug #SF3545490: If the body handed to the library was missing a trailing line terminator, then dkim_canon_closebody() would end the hashes with some data not included. Now, if DKIM_LIBFLAGS_FIXCRLF is set, it will detect this condition and correct it; if not, an error is returned. Problem noted by James Erickson. LIBOPENDKIM: If the job ID passed in during handle creation includes slashes and temporary file creation is enabled, convert the slashes to dots in the temporary file template. Problem noted by James Erickson. 2.6.5 2012/07/14 Swap order of "header.d" and "header.i" values in Authentication-Results fields. BUILD: Fix bug #SF3543282: Corrections to Darwin/libar build adjustment made in 2.6.3. Problem noted by Daniel J. Luke. 2.6.4 2012/07/12 Feature request #SF3542099: Include "header.d" in all Authentication-Results fields, not just "header.i". This makes life easier for users of OpenDMARC. BUILD: Fix SHA256 test on some systems. Problem noted by James Erickson. 2.6.3 2012/07/11 Add "ResolvConf" setting, allowing the ability to pass a resolv.conf-like file to unbound to allow specific nameservers to be used instead of the default. LIBOPENDKIM: Return the correct error code when a SHA1-only library encounters a SHA1 signature that references a SHA256-only key. Problem noted by Andrew Birchall. LIBAR: Add ar_resolvconf(). BUILD: Fix bug #SF3538676: Build with -DDARWIN on MacOSX, and default to arlib if unbound isn't selected. Patch from Daniel J. Luke. 2.6.2 2012/07/02 Fix build confusion between _FFR_RATE_LIMIT and _FFR_RESIGN. Problem noted by Rolf Sonneveld. Fix bug #SF3538639: Fix error when --domain is not provided to opendkim-genrates. Problem noted by Andreas Schulze. Fix bug #SF3539449: Clarify legal "Socket" values. Requested by Scott Kitterman. Fix bug #SF3539493: Handle certain cases of data set names that appear to be comma-separated lists which include IPv6 addresses. Reported by Scott Kitterman. 2.6.1 2012/06/25 Restore and activate _FFR_SELECT_CANONICALIZATION. Also adds a SelectCanonicalizationHeader configuration option. Remove _FFR_SELECTOR_HEADER. Update Authentication-Results parsing to understand "dkim-atps" (RFC6541) and no longer understand "hardfail" (RFC6577). LIBAR: Fix bug #SF3309946: Ensure the dispatcher doesn't hold the master lock when it might enter a read wait. STATS: Add a database index on messages.msgtime to aid with expiration performance. TOOLS: Feature request #SF3536385: Add "-a" to opendkim-genkey to include a domain name in the generated TXT record. Requested by Quanah Gibson-Mount. 2.6.0 2012/06/07 Feature request #SF3495969: Add support for Lua v5.2.0. Requested by Rolf Sonneveld. Feature request #SF3502777: Log all authentication results rather than relying on logging of Authentication-Results header fields. Requested by Andreas Schulze. Feature request #SF3512286: Add "LDAPSoftStart" flag so the filter doesn't abort on startup when LDAP is not available. Feature request #SF3512836: Add _FFR_SOCKETDB, which enables support for a generic socket data set. Feature request #SF3514982: Add Erlang data set support. Patch provided by Andre Nathan. Feature request #SF3516253: Update to newest "repute" working group documents, which mainly means adding JSON support and promoting application-specific extensions to the top level in the reputon structure. Feature request #SF3518593: Add support for OpenLDAP's MDB as a data set backend. Requested by Quanah Gibson-Mount. Feature request #SF3519002: Put reason information inside a "reason" tag in Authentication-Results header fields rather than in comments. Feature request #SF3521000: Log hostname and daemon name (taken from macros) when logging "no MTA name match". Requested by Andreas Schulze. Feature request #SF3524756: Add ability to request TCP keepalive features via the OpenLDAP client library. Requested by Quanah Gibson-Mount. Feature request #SF3529233: Add odkim.get_envfrom() to all Lua scripts. Requested by Charles Cazabon. Fix bug #SF3518877: Separate variable expansion from literal text in opendkim-genkey. Fix bug #SF3522883: Allow TLS for ldapi URIs. Problem noted by Quanah Gibson-Mount. Fix bug #SF3527428: Construct the LDAP URI list properly, rather than only keeping the last one, and add failover code. Problems noted by Quanah Gibson-Mount. Patch #SF3522895: Add contrib/ldap/opendkim.ldif. Contributed by Quanah Gibson-Mount. Activate _FFR_XTAGS. Remove _FFR_SELECT_CANONICALIZATION. LIBAR: Fix bug #SF3444318: Do proper buffer size calculations to avoid valgrind warnings about references to unaddressable space. Reported by Todd Lyons. LIBOPENDKIM: Fix bug #SF3496041: Remove _FFR_PARSETIME. LIBOPENDKIM: Fix bug #SF3516653: By default, treat a syntax error in an ADSP record as an NXDOMAIN. Add new library flag DKIM_LIBFLAGS_REPORTBADADSP to restore the original behaviour. Suggested by Scott Kitterman. LIBOPENDKIM: Fix bug #SF3524865: Disallow generation of signatures where signer and signing domain don't match per the DKIM specification. Add DKIM_LIBFLAGS_DROPSIGNER which, if set, will still generate signatures in that case, but with the signer omitted so the signature is still compliant. BUILD: Fix bug #SF3425384: Add missing support for compiling against libevent2, which is an option for unbound. Noted by Andreas Schulze. BUILD: Fix bug #SF3475799: Don't do a manual check for libdb.a. Use the AC_CHECK_* macros instead. DOCS: Fix bug #SF3518864: The license for IETF documents is not compatible with free software licensing, which makes packaging a bit of a chore. Replace all the text files in the "docs" directory with a single HTML page that includes links to all the things we used to include here. Requested by Scott Kitterman. STATS: Feature request #SF3110059: Move opendkim-reportstats from contrib/stats to stats, making it fully supported. STATS: Feature request #SF3525786: Add opendkim-expire script. Requested by Andreas Schulze. STATS: Feature request #SF3528652: Allow a specific list of domains, possibly read from a file, for opendkim-gengraphs and opendkim-genrates. Requested by Andreas Schulze. 2.5.2 2012/04/09 Fix bug #SF3496208: Replace stats/opendkim-genstats with a perl script so it's far more efficient. Fix bug #SF3514793: Pass proper flags to libdb when creating temporary LDAP caches. Problem noted by Sergey Romanov. Fix a crash bug when using LocalADSP with a message with no parseable From: field. Problem noted by John Merriam. Fix a crash bug when using LDAP with authentication when LDAPAuthUser is not defined. Problem noted by Christian Roessner. STATS: Fix bug #SF3510729: Convert stats/opendkim-gengraphs to a perl script. 2.5.1 2012/03/15 Fix bug #SF3496131: Fix query cache build problem. Reported by Dilian Wesselinov Palauzov. Fix bug #SF3500660: Add Date: header field to generated reports. Reported by Andreas Schulze. BUILD: A few subsidiary libraries need to know about -lresolv on systems that need it. Reported by Scott Kitterman. STATS: Add "-E" command line flag to opendkim-importstats, forcing an abort on any input error. 2.5.0 2012/02/29 ##################################################################### ### ### ### This release is dedicated to the memory of J.D. Falk, a ### ### tireless champion of anti-abuse technology and collaboration ### ### and a founding member of the Board of the Trusted Domain ### ### Project, a participant in related IETF work, and a long-time ### ### particpant and supporter of MAAWG. J.D. was taken by cancer ### ### on November 16, 2011. His enthusiasm and perspective for ### ### all of this work will be sorely missed. ### ### ### ##################################################################### Feature request #SF3385816: Discontinue DomainKeys support. Feature request #SF3393282: Update ARF output per draft-ietf-marf-authfailure-report-03 et seq. Feature request #SF3406814: Add ability to invoke chroot(). Requested by Andreas Schulze. Feature request #SF3477908: Update DKIM reporting per draft-ietf-marf-dkim-reporting-10. Add "WeakSyntaxChecks" suppressing some short-circuiting error checks on syntax. Requested by Todd Nagengast. Allow a set of test files to be passed via "-t" rather than just one. Add _FFR_REPUTATION, and several new support libraries (in the libut/ and reputation/ directories) for doing DKIM-based reputation evaluations of arriving messages. Full documentation of the algorithms will appear in an upcoming white paper. This also includes several new configuration options that make use of reputation data pulled from servers: ReputationCache ReputationCacheTTL ReputationLimits ReputationLowTime ReputationMinimum ReputationLimitModifiers ReputationRatios ReputationSpamCheck ReputationTimeFactor For now these are briefly documented in reputation/README. As this subsystem matures, they will be fully documented in opendkim.conf(5). Fix bug #SF3471520: Don't crash when the first line of a configuration file is an "Include" instruction. Reported by Dilian Wesselinov Palauzov. Fix bug #SF3475149: Apply RFC2254 encoding to LDAP queries. Problem noted by Yoshiaki Yanagihara. LIBOPENDKIM: Feature request #SF3317160: Per RFC6376, remove granularity checks. LIBOPENDKIM: Feature request #SF3385768: Add dkim_privkey_load(), allowing validation of a private key before reaching end-of-message. Requested by Heikki Gruner. LIBOPENDKIM: Feature request #SF3423226: Copy header field name lists instead of using the caller's copy. Suggested by Heikki Gruner. LIBOPENDKIM: Update list of header fields that should be signed per RFC6376. LIBOPENDKIM: Don't report the absence of "c=" as an error, since there is a default. LIBOPENDKIM: Add DKIM_SIG_CHECK() macro. Suggested by Heikki Gruner. LIBAR: Fix bug #SF2917856: Rename "ar.h" to "async-resolv.h" since "ar.h" is already in common use. STATS: Feature request #SF3397903: Drop all support for data needed for the DKIM Implementation Report, as it has been completed. Leave stuff that's useful for reputation R&D. STATS: Feature request #SF3402857: Modify opendkim-spam to be able to write update records to statistics files. STATS: Feature request #SF3439384: Make opendkim-importstats more backend-agnostic. Requested by Andreas Schulze. TOOLS: Add opendkim-testmsg, for signing/verifying messages without all the milter code being invoked. Requested by Todd Nagengast. CONTRIB: Add LDAP documentation and examples. Provided by Patrick Ben Koetter. 2.4.3 2011/12/26 Fix bug #SF3400670: Send ADSP failure reports when rejecting a message. Reported by Andreas Schulze. Fix bug #SF3419149: Add MaximumSignedBytes to opendkim-config.h. Reported by Adam Bernstein. Fix bug #SF3441240: Apply ReportBccAddress when generating ADSP reports. Reported by Richard Rognlie. Fix bug #SF3447199: Fix logic preventing the application of the BodyLengthDB. Problem noted by Richard Rognlie. Fix Authentication-Results generation with "AddAllSignatureResults" enabled. Reported by Todd Nagengast. Fix a crash bug when trying to handle certain malformed header fields in verify-only mode. Reported by Todd Lyons. Improve error checking in the callback provided to libunbound to avoid crashes. Problem noted by Todd Lyons. Cope with versions of Sleepycat DB that crash when asking for a file descriptor for in-memory databases. Problem reported by Todd Lyons. Don't override "On-NoSignature" when "Quarantine" is set. Reported by Jarry Jeremy. Ignore header field names that contain semi-colons, as they produce syntactically invalid signatures. Problem noted by Heikki Gruner. LIBOPENDKIM: Fix bug #SF3465400: Don't use "new" as a parameter name in dkim.h since that's an error for C++. Reported by Amit Schreiber. LIBOPENDKIM: NOERROR is the same as NXDOMAIN for the purposes of the ADSP existence check. Problem noted by Todd Nagengast. LIBOPENDKIM: Return DKIM_STAT_SYNTAX from dkim_header() if the header field name contained a semi-colon. LIBAR: After computing a timeout, if the fractional seconds portion adds to exactly a second, convert that amount to seconds. Previous versions only converted when the fractional portion exceeded a second. This led to threads that spin indefinitely. Problem noted by Todd Lyons and Gary Mills; forensic evidence revealing the problem at long last provided by Todd Lyons. STATS: Fix a crash bug in opendkim-importstats due to improper handling of NULL returns from SQL. Reported by Andreas Schulze. 2.4.2 2011/08/05 Don't apply BodyLengthDB when not signing. Problem noted by Andreas Schulze. LIBOPENDKIM: Update for draft-kucherawy-dkim-atps-06. LIBOPENDKIM: Terminate the strings returned by dkim_sig_getsubstring() and dkim_sig_getidentity() whenever possible. Suggested by Heikki Gruner. CONTRIB: Change "chkconfig" instruction in RHEL init script, and a minor tweak to the RPM spec file. From Steve Jenkins. 2.4.1 2011/06/28 Fix bug #SF3312691: Add "-e" command line switch to extract a value from configuration. Fix bug #SF3324488: Accommodate postfix's job ID generation by moving the BodyLengthDB check down to EOH. Reported by Andreas Schulze. Fix bug #SF3327106: Fix mode-based short-circuit logic. Reported by Yoshiaki Yanagihara. Patch #SF3321766: Remove "-d" from usage message (not implemented). Patch from Andreas Schulze. Print database error strings instead of just return codes in query test mode, and clean up error strings when extracting them from the layers below. Minor fixes related to use of OpenDBX. LIBOPENDKIM: Fix bug #SF3328330: Correct generation of "z=" tags. Problem reported by Christophe Wolfhugel. LIBOPENDKIM: Patch #SF3313534: Improve thread-safe use of OpenSSL in dkim_init() and dkim_free(). Patch from Masatake Daimon. LIBOPENDKIM: Patch #SF3314269: Change all uses of off_t to ssize_t, as the former is reserved for use with filesystem APIs. Patch from Manuel Mausz. LIBOPENDKIM: Make the user context pointer (void) rather than (const void) since the caller is allowed to change it. Problem noted by Heikki Gruner. LIBOPENDKIM: Proper handling of DKIM_CBSTAT_ERROR from the prescreen and final callbacks. Problem noted by Heikki Gruner. LIBOPENDKIM: Fix up initialization under _FFR_OVERSIGN. Problem noted by Eray Aslan. BUILD: Adjust gprof code to accomodate systems that put profiling output in .gmon rather than gmon.out. 2.4.0 2011/06/06 Feature request #SF3060140: Extension of odkim.sign() to include maximum signed byte count. Feature request #SF3171865: Add _FFR_LUA_GLOBALS, enabling a mechanism to maintain state between Lua scripts. Feature request #SF3241982: Optionally add an Authentication-Results field for all signatures present, not just the first good one. Feature request #SF3256630: Add _FFR_RATE_LIMIT, enabling hooks for post-verification rate controls. Feature request #SF3290461: Add optional support for querying a memcache daemon via libmemcached. Feature request #SF3299041: Be tougher on use of the "l=" tag by removing "BodyLengths", renaming "BodyLengthDBFile" to "BodyLengthDB", and allowing pattern matches. This effectively activates _FFR_BODYLENGTH_DB as well. Feature request #SF3303911: Add "DisableADSP" setting. In the stats recording code, only check for a domain match for signatures that don't have errors (i.e., short circuit if sigerror is not zero). LIBOPENDKIM: Feature request #SF2969516: Teach dkim_chunk() about DKIM_LIBFLAGS_FIXCRLF. LIBOPENDKIM: Feature request #SF3123731: Extend FixCRLF to cover header fields. LIBOPENDKIM: Feature request #SF3151534: Extract DKIM reputation support to its own library. LIBOPENDKIM: Feature request #SF3279589: Add _FFR_XTAGS, adding support for generic extension tags in signatures. LIBOPENDKIM: Feature request #SF3300738: Add dkim_sig_getqueries() and dkim_policy_getqueries() to assist API consumers that have their own DNS mechanisms not directly adaptable to ours. Requested by Heikki Gruner. LIBOPENDKIM: Return an error from dkim_getsighdr() or dkim_getsighdr_d() if called after a key load failure. Problem noted by Heikki Gruner. LIBAR: Check that the descriptor's write socket is writable before calling ar_sendquery() when trying to identify open requests that need retransmission. STATS: Feature request #SF3066106: Add "opendkim-anonstats" tool. CONTRIB: Paths in init/redhat/opendkim are now auto-generated. Activate _FFR_MAXVERIFY. 2.3.2 2011/04/14 Fix bug #SF3067338: Create a pool of DB handles for SQL operations so that queries don't all share one serially. Fix bug #SF3156559: Don't compile Lua scripts anew for each execution. Fix bug #SF3210385: Fix issue with configuration reload failures having some side effects on the remaining active configuration handle. Reported by Andreas Schulze. Fix bug #SF3235131: Don't report ADSP errors as signature errors in Authentication-Results header fields. Fix bug #SF3258459: Don't send progress messages during EOH. Problem reported by Gary Mills. Add ADSP processing error information to A-R header fields. LIBOPENDKIM: Fix bug #SF3276469: When generating "z=" tags, apply omit and sign header field lists. Problem noted by Todd Lyons. LIBOPENDKIM: Use a time_t to store TTL and clock drift options rather than unsigned long. Patch from Piotr Sikora. LIBAR: Include class and type in debugging messages. Suggested by Gary Mills. LIBAR: Start the dispatcher on the first query, not in ar_init(). Allows ar_init() to be called before a fork() safely. CONTRIB: Adjust installed path in RedHat start script. Patch from Naresh V. CONTRIB: Require the current libopendkim in the opendkim definition in the RPM spec file. Patch from Naresh V. 2.3.1 2011/03/28 Feature request #SF3196060: Log retrieved reputation values. Patch from Andreas Schulze. Feature request #SF3199824: Don't log "no signature data" unless LogWhy is enabled or the action for unsigned mail is something other than "accept". Fix bug #SF3196069: Log more detail when dkimf_config_setlib() fails. Problem noted by Andreas Schulze. Fix bug #SF3197890: Update ARF report format for DKIM verification failures to use what's in draft-ietf-dkim-marf-reporting. Fix bug #SF3204725: Add "ReplaceHeaders" data set to constrain what header fields are affected by "ReplaceRules". Problem noted by Chris Callegari. Fix bug #SF3211114: Extract "BaseDirectory" from configuration file properly. Fix bug #SF3234178: Correct handling of a KeyTable entry for which the key data is empty. Based on a patch from Yoshiaki Yanagihara. Patch #SF3205699: Make all header field name and domain name data sets case insensitive. Submitted by Richard Rognlie. Add a case-insensitivity flag to odkim.db_open(). Minor correction to DNS function return codes for unbound, which doesn't have an expired/no-reply distinction like libar does. LIBOPENDKIM: Fix up timeout handling with a DNS callback is in use. LIBOPENDKIM: Update for draft-kucherawy-dkim-atps-03. STATS: Fix bug #SF3195449: Omit data from reporters that are not currently marked "enabled" in the reporters table. STATS: Evaluate "i=" against the "d=" domain, not the "From" domain. Problem noted by Mark Martinec. STATS: A few more reports. MILTERTEST: Don't use non-standard printf() conversions. MILTERTEST: Get the SMFIP_HDR_LEADSPC logic right. TOOLS: Feature request #SF3200848: Add a backgrounding option (on by default) to opendkim-spam. 2.3.0 2011/02/21 Feature request #SF2964396: Allow SignHeaders, OmitHeaders and SenderHeaders to be specified as deltas to the default lists. Feature request #SF3053094: Correct documentation and improve function of the AuthservID configuration setting. Requested by Andreas Schulze. Feature request #SF3060152: Add odkim.replace_header() function. Feature request #SF3060161: Add odkim.del_header() function. Feature request #SF3061189: Add new "quarantine" option to all the various "On-" settings. Feature request #SF3066104: Add "AnonymousDomains" configuration option. Feature request #SF3074290: Add _FFR_ATPS, experimental support for draft-kucherawy-dkim-atps. Feature request #SF3076684: Add "VBR-TrustedCertifiersOnly" flag. Feature request #SF3080604: Add odkim.parse_field() function. Requested by Todd Lyons. Feature request #SF3081697: Add "OversignHeaders" configuration option. Feature request #SF3085536: Activate _FFR_STATS_I, providing statistics reporting about use of "i=" in signatures. Feature request #SF3096630: Add odkim.rbl_check() function. Feature request #SF3097083: Make SigningTable accessible from Lua. Feature request #SF3103095: Allow "%" in a KeyTable entry's filename component as well as the domain name. Feature request #SF3105480: Improved VBR correctness; don't conduct VBR checks at all if there are disagreeing "mc" values in multiple VBR-Info header fields. Feature request #SF3106132: Allow "%" in a SigningTable's value. Feature request #SF3109963: Add "MaximumSignaturesToVerify" setting. Suggested by John Wood. Feature request #SF3110593: Add compile-time support for GnuTLS as an alternative to OpenSSL. Suggested by Alessandro Vesely. Feature request #SF3136772: Sign the VBR-Info header field, if added. Requested by Frederik Pettai. Fix bug #SF3134119: With AutoRestart enabled, arrange to relay SIGUSR1 from the parent to the child rather than terminating. Reported by Yoshiaki Yanagihara. Fix bug #SF3141313: Trim whitespace from values in in-core data sets. Reported by Todd Lyons. Fix bug #SF3156124: More robust handling of database disconnects. Also add _FFR_POSTGRESQL_RECONNECT_HACK, which will hopefully be temporary. Reported by Miha Vrhovnik. Fix bug #SF3181180: Correct handling of quoted strings containing parentheses (and the opposite) when parsing Authentication-Results header fields. Reported by Mark Martinec. Fix back-compatibility with very old implementations of milter in MTAs. Fix case-insensitive matching for domain names when doing signing selection. Problem noted by John Espiro. New configuration file options: - "CaptureUnknownErrors", replacing the FFR of the same name - "DNSConnect", requesting the resolver use TCP mode - "KeepAuthResults", suppressing required removal of Authentication-Results header fields - "ResolverTracing", adding detailed logging of libar activity - "StrictHeaders", requesing libopendkim to assert header field counts according to the standards - "UnboundConfigFile", passing a configuration file name to libunbound (suggested by Andreas Schulze) - "VBR-PurgeFields", removing "X-VBR-*" fields after using them Trim whitespace from the end of all values in a config file, not just strings. Problem noted by Reuben Farrelly. Assume a default location for opendkim.conf. Suggested by Andreas Schulze. Don't needlessly demand milter features, causing aborts when they're not available. Problem noted by Todd Lyons. Make odkim.get_clienthost(), odkim.get_clientip() and odkim.get_fromdomain() available in the final script. When "SyslogSuccess" is active, log the selector and domain used. Suggested by Miha Vrhovnik. LIBAR: Feature request #SF3115073: Add flag for fine-grained activity logging for debugging purposes. LIBAR: Add support for using poll() instead of socket(). LIBOPENDKIM: Feature request #SF3087029: Add DKIM_LIBFLAGS_STRICTHDRS. LIBOPENDKIM: Feature request #SF3089990: Add dkim_sig_getsignedhdrs(). LIBOPENDKIM: Fix bug #SF3079094: Have dkim_diffheaders() take canonicalization into account when generating its results to avoid false positives. LIBOPENDKIM: Fix bug #SF3184670: Add error codes for missing and empty "v=" tags, thus avoiding a possible assertion failure when DKIM_LIBFLAGS_BADSIGHANDLES is in use. Reported by J. Coloos. LIBOPENDKIM: Fix up handling of multi-TXT DNS replies inside dkim_get_policy_dns(). LIBOPENDKIM: Add dkim_getid(). LIBOPENDKIM: Treat no answers as an NXDOMAIN with respect to retrieving ADSP records. LIBOPENDKIM: When an unexpected DNS type or class is received, log the received values. LIBVBR: Feature request #SF3105477: Copy the generic DNS work from libopendkim. LIBVBR: Feature request #SF3127200: Add proper documentation (i.e., a man page). STATS: Feature request #SF3085536: Activate _FFR_STATS_I, providing statistics reporting about use of "i=" in signatures. STATS: Feature request #SF3125701: Add "s=" key value tracking. STATS: Feature request #SF3137445: Track key sizes. Suggested by Todd Lyons. MILTERTEST: When asserting negotiation state, don't forget to capture what was negotiated. TOOLS: Feature request #SF3106876: Amend opendkim-testkey to return the DNSSEC results as well. TOOLS: Feature request #SF3074290: Add a zone file generation tool for ATPS. TOOLS: Fix bug #SF3143922: Command line parameters to opendkim-testkey now override their configuration file counterparts. TOOLS: Experimental new "opendkim-spam" tool to let users update a stats database to indicate a message is spam, for possible later correlation use. BUILD: opendkim-genzone needs LIBCRYPTO_LDFLAGS. Reported by John Smith. Activate _FFR_CAPTURE_UNKNOWN_ERRORS. 2.2.2 2010/11/28 Fix bug #SF2903325: Clean up numerous signed vs. unsigned warnings. Fix bug #SF3095782: When VBR is enabled, only perform a query when the "md" domain in the VBR-Info header field matches the "d" field for any valid signature. Fix bug #SF3105993: Better handling of missing records in Lua DB lookups. Reported by Luci Stanescu. When reading keys, ensure what's being read is a regular file and not something else. Complain if TrustAnchorFile names something that can't be opened for reading. LIBOPENDKIM: Don't complain about multiple records returned if one of them was an RRSIG. Problem noted by Andreas Schulze. LIBAR: Rework some I/O logic to avoid a deadlock when the nameserver becomes unresponsive during response processing. Problem noted by Gary Mills. BUILD: Move all scripts and executables except opendkim to a bin directory for adminstrator convenience. They were previously in sbin. BUILD: Fix bug #SF3101842: Fix opendkim-genzone build when OpenDBX is in use. BUILD: opendkim-testkey can require SASL build information when used with OpenLDAP, or Lua information when built with Lua. BUILD: Dissociate libopendkim and libunbound, as this is now handled through the application rather than the library. BUILD: Convert to using git for source code management. STATS: Additional reporting improvements. STATS: Fix bug #SF3107659: Add additional diagnostic output to opendkim-importstats when malformed input is found. TOOLS: Handle input generated with and without the _FFR_STATS_I extensions. Problem noted by Graham Murray. 2.2.1 2010/10/25 Avoid assertion failures when using "-V" and arlib. Fix "refile" loading. Problem noted by Steve Jenkins. Fix collision between "ReputationRoot" and "StatisticsName" in the configuration file. Reported by Andreas Schulze. Convert sender's domain name to lowercase prior to doing any database queries with it. This was done before, but lost during the database overhaul in 1.2.0. Reported by Gary Mills. Fix up Authentication-Results header field generation for VBR. Reported by Fredrik Pettai. Add _FFR_STATS_I enabling statistics reporting of "i=" signature properties. LIBOPENDKIM: Fix bug #SF3081964: dkim.h requires . Patch from Kaspar Brand. LIBOPENDKIM: Fix bug #SF3087251: Use thread-safe resolver functions when avaialble. Problem noted by Christian Pelissier. LIBOPENDKIM: Cancel completed reputation queries. Problem noted by John Wood. LIBOPENDKIM: Simplify DKIM_OPTS_ALWAYSHDRS handling. LIBAR: Fix bug #SF3080720: Don't compute timeouts based on completed or dead queries. Problem noted by John Wood. LIBVBR: Fix some pointer errors causing false negatives. Problem noted by Fredrik Pettai. TOOLS: Write "v=" tags in key records output by opendkim-genzone. 2.2.0 2010/10/03 Feature request #SF2874043: Add _FFR_ADSP_LISTS allowing control over action taken when mail is sent to known lists from ADSP "discardable" sources. Feature request #SF2964366: Allow arbitrary data set operations from inside Lua script hooks. Feature request #SF2981598: Add "NoHeaderB" and "SingleAuthResult" settings so that only one Authentication-Results header field is added, and reduce its variability. Requested by Gary Mills. Feature request #SF3013084: Add "DomainKeysCompat" setting. Feature request #SF3017358: Allow a token in the KeyTable that gets replaced with the sender's domain name. Feature request #SF3019876: Enable registration and use of generic DNS functions. Feature request #SF3021566: Change "ADSPDiscard" to "ADSPAction", allowing selection of what action to take when a message is determined by ADSP to be "discardable". Feature request #SF3023232: Allow selection of a signer (for the signature's "i=" tag) when calling odkim.sign() or via an optional second parameter in the SigningTable. Feature request #SF3024854: Always log a warning if a key file has unsafe group/other read/write bits set. Further, if the new "RequireSafeKeys" setting is true, refuse to use the data. Feature request #SF3030548: Add _FFR_DEFAULT_SENDER, adding the "DefaultSender" setting. Requested by Andreas Schulze. Feature request #SF3049483: Use ReportAddress for ADSP Reports and for the sender envelope address. Reported by Andreas Schulze. Feature request #SF3056571: Extend signer selection in the SigningTable to include a token that will be replaced by the From: domain. Requested by Richard Rognlie. Feature request #SF3062077: Allow the specification of additional recipients when delivering DKIM/ADSP failure reports through a new ReportBccAddress configuration option. Requested by Andreas Schulze. Fix bug #SF3004995: Don't apply "SenderHeaders" to the library as that impacts how ADSP works. Fix bug #SF3025856: Fix "AllowSHA1Only", which was not working at all. Fix bug #SF3037504: Rework database schema and tools to meet revised reporting requirements. Fix bug #SF3051536: Allow disabling of reputation queries. Requested by Andreas Schulze. Fix bug #SF3058204: Fix numerous possible double-free() incidents in dkimf_config_free(). Reported by Richard Rognlie. Fix PeerList to work with IPv6 addresses. Fix loop boundary check in dkimf_db_close(). Reported by Richard Rognlie. Fix assertion failure in dkimf_db_get() when used with a "match both" operation. Reported by Richard Rognlie. Fix "LocalADSP", which was not working at all. Fix some Lua test mode logic and a build issue that prevented "ScreenPolicyScript" from working. Added MTACommand for overriding default (mainly for testing). Ignore "Domain" and "Selector" settings if "KeyTable" is set. Problem noted by Rolf Sonneveld. Add "On-PolicyError" to configuration tables. Reported by Richard Rognlie. Don't automatically temp-fail messages bearing signatures that reference revoked keys. Some fixes to the "final" Lua script self-test code. Include libmilter version in "-V" output. Single-thread DB queries done via OpenDBX handles as they can't be used to do parallel queries. Attempt to reconnect after SQL disconnections. Revise text/plain portion of policy reports. Noted by Andreas Schulze. Fix up DSN parsing so that it is not needlessly restrictive. Reported by Todd Lyons. Add _FFR_STATSEXT: Allows arbitrary local extensions to statistics gathering via a fourth Lua script that can cause the generation of additional SQL insertion operations. LIBOPENDKIM: Feature request #SF3026287: Add dkim_getuser() function. Requested by Ale Vesely. LIBOPENDKIM: Feature request #SF3065035: Apply library query configuration to ADSP lookups as well, mainly to support auotmated testing. LIBOPENDKIM: Fix bug #SF3071368: Fix tiny memory leak in dkim_init(). Reported by Al Garcia. LIBOPENDKIM: Fix bug #SF3051762: Don't error out of dkim_get_key() when in test mode by testing signature-specific features when against dummy data. Problem noted by Andreas Schulze. LIBOPENDKIM: Don't build against pthread libraries if not needed. Requested by Ale Vesely. LIBOPENDKIM: Add dkim_get_signer(), dkim_policy_state_new() and dkim_policy_state_free(). LIBOPENDKIM: Don't assert a "g=" default when processing keys so that statistics reporting can tell whether or not it was originally there. LIBOPENDKIM: Minor fix to internal state machine when dealing with unsigned messages. LIBOPENDKIM: Rename DKIM_PRESULT_AUTHOR to DKIM_PRESULT_FOUND. LIBOPENDKIM: Improved error reporting from dkim_ohdrs(). LIBOPENDKIM: Improved re-entrancy of dkim_eoh_verify(), requested by Frederik Deweerdt. LIBOPENDKIM: Undefine DKIM_FEATURE_ASYNC_DNS (obsolete). LIBOPENDKIM: Rework logic implementing "AlwaysSignHeaders". MILTERTEST: Feature request #SF3005002: Enable testing of "unspecified" protocol family connections. MILTERTEST: Add "-u" option to report resource usage statistics on completion. MILTERTEST: Add mt.signal() to allow signaling of filters for things like configuration file reloads. MILTERTEST: Enhance mt.connect() to accept optional retry and interval arguments. MILTERTEST: Add "-w" option to request no waiting for the child process to exit and report status. MILTERTEST: Allow partial seconds argument to mt.sleep(). TOOLS: Feature request #SF3004335: Add support to opendkim-testkey to get configuration file values and validate an entire KeyTable. TOOLS: Update opendkim-genkeys script to support draft-ietf-marf-dkim-reporting. TOOLS: Flip logic of "-a" flag to opendkim-stats. TOOLS: Fix bug #SF3037452: Change owner/group/mode of stats database when resetting it to whatever the replaced file had. Problem noted by Andreas Schulze. CONTRIB: Add opendkim-reportstats, contributed by John Wood. BUILD: Fix --with-db. Reported by John Wood. Activate _FFR_ZTAGS. 2.1.3 2010/07/15 Fix build when enabling LDAP. Fix portability issue with DB 1.x. Patch from Kaspar Brand. Fix bug #SF3026261: Don't try to open the statistics database before possibly changing userid. Reported by Andreas Schulze. Plug a couple of potential but minor memory leaks, avoid some NULL dereferences, rewrite some clearly incorrect code, and several other fixes found by a code analysis tool, used by courtesy of Cloudmark. Restore "-P" to the command line as it's convenient for start/stop scripts. MILTERTEST: Support multiple macro values in mt_macros(). BUILD: Improved support for Sleepycat DB file locations. 2.1.2 2010/07/06 When testing the domains data set for a domain match for signing, check for an explicit "*" record for back-compatibility with versions prior to v1.2.0. Avoid segmentation faults when colon-separated data in a data set isn't formatted properly or has too few fields. Add additional database error logging. Rework OpenDBX query function use for correctness. Problem reported by Naresh V. Fix an internal database call that caused false errors to be reported with recent DB versions. Fix bug #SF3021228: Avoid a NULL dereference in dkimf_xs_requestsig() when the function is called in test mode. Fix bug #SF3022409: Improve error logging from dkimf_db_open(). Patch #SF3023224: Fix up a man page generation warning for opendkim(8). From Andreas Schulze. Patch #SF3023521: Tidy up some compiler warnings. From Andreas Schulze. BUILD: opendkim-stats needs to know where to find the OpenSSL includes. Reported by Andreas Schulze. TOOLS: Patch #SF3023404: Fix up opendkim-stats usage message. From Andreas Schulze. MILTERTEST: Fix bug #SF3020662: Add compatibility with older versions of libmilter. Problem reported by Naresh V. 2.1.1 2010/06/22 Force IPv6 addresses to lowercase, which is about to become standard (see draft-ietf-6man-text-addr-representation). Problem noted by Reuben Farrelly. Permit configurations in which KeyTable and SetupPolicyScript are defined but SigningTable isn't. Return an error when making a default signing request if KeyFile and Selector were not both specified. Fix odkim.sign() so that it pulls from the correct Lua stack index, avoiding a NULL dereference and a crash. Problem noted by Jozsef Kovacs. Fix bug #SF3015441: Argument processing for odkim.log() was incorrect. Problem reported by Jozsef Kovacs. Fix bug #SF3016124: odbx_field_value() returns NULL if the requested column contains an SQL NULL. Problem reported by Jozsef Kovacs. Patch #SF3015439: Fix bugs in data set name parsing (e.g. allow dots in fields so that fully qualified hostnames can be given). Patch from Jozsef Kovacs. MILTERTEST: Fix bug #SF3005615: Observe negotiated SMFIP_NO* protocol option bits. 2.1.0 2010/06/07 Feature request #SF2964369: Add _FFR_LDAP_CACHING to cache and share common LDAP queries using an internal query cache for better optimization of LDAP resources. Feature request #SF2964378: Overhaul statistics collection code enabled by "--enable-stats". See stats/README for details. Feature request #SF2964380: Do some limited pattern matching for ResignMailTo. Feature request #SF2964381: The value in the ResignMailTo data set can now name a key in the KeyTable to use when re-signing a message. Feature request #SF2964388: Add a "lua" dataset type. Feature request #SF3007640: Add odkim.add_header() function, available to the final script. Log more information when loading data from the KeyTable fails. Remove several command line options that are redundant to the configuration file and not useful in test mode. These include: -a, -C, -h, -i, -I, -m, -M, -P, -R and -U. Add support for draft-kucherawy-authres-header-b. Properly deal with critical errors from libdb that otherwise lead to a descriptor leak (because the close operation fails). Reported by Warren Horvath; data provided by Graham Murray. Don't allow Domain without KeyFile and Selector, which causes an assertion failure when calling dkim_sign(). Problem noted by Todd Lyons. Fix configuration logic around DontSignMailTo that prevented it from working. Reported by Warren Horvath. When data set open operations fail during configuration file processing, report the name of the data set instead of just the error. CONTRIB: Patch #SF3010443: Improvements to opendkim.init and opendkim.spec from Kaspar Brand. LIBOPENDKIM: Add dkim_get_sigsubstring(), required for "header.b" production on Authentication-Results: header fields. LIBOPENDKIM: Initialize canon_buf in dkim_add_canon() to avoid a garbage dereference later during an abort. MILTERTEST: Fix SMFIR_ADDHEADER tests. STATS: Add "stats" subdirectory including tools for collecting and reporting aggregated statistics. TOOLS: Feature request #SF2964364: Have opendkim-genzone use the KeyTable if defined in a provided configuration file. 2.0.4 2010/05/17 Fix logic enabling AlwaysAddARHeader. Reported by Thomas Arnett. Return SMFIR_SKIP if available when reaching mlfi_body() if the filter is not interested in the body, such as on an unsigned message. Add more unit tests (but many more are needed). LIBOPENDKIM: In dkim_eoh() when verifying, set the DKIM error string to something if there was at least one signature on the message but none passed. MILTERTEST: Add SMFIR_SKIP as a testable milter reply code. MILTERTEST: Add mt.chdir(). 2.0.3 2010/04/30 Fix bug #SF2986301: Initialize a pointer for AutoRestart before using it, avoiding a segmentation fault. Fix bug #SF2992571: Rename _FFR_DNS_UPGRADE to _FFR_DNSUPGRADE to match what the build system does. Problem noted by Gary Mills. Don't let Authentication-Results: logic from DomainKeys verification interfere with that of DKIM verification. MILTERTEST: Break out of the sending loop in mt_bodyrandom() if something other than SMFIR_CONTINUE comes back from the MTA. MILTERTEST: Add support for milter's UNKNOWN and DATA steps. MILTERTEST: Fix bug #SF2991011: Honour SMFIP_NR_* no-reply requests that may have been made by the filter. 2.0.2 2010/04/12 Fix bug #SF2983979: Fix a configuration buffer initialization error tripped when running in test mode. Patch from Kaspar Brand. LIBOPENDKIM: Fix dkim_chunk() to handle a message that starts with a CRLF. Problem noted by Masumi Taketomi Parekh of Yahoo!. BUILD: Fix bug #SF2981597: Incorrect variable check for "--with-domainkeys" when a path is given, and repair DomainKeys build in opendkim/Makefile.am. Reported by Gary Mills. BUILD: Fix bug #SF2983206: Optionally pass "-rpath" to libtool for libopendkim. BUILD: Path fix in opendkim.pc from Stefan Schulze Frielinghaus. 2.0.1 2010/03/20 Fix bug #SF2964376: Don't use dkim_getsighdr() internally during signing as it presumes signatures will fit within a bounded character array and sometimes (e.g. with extensive data in a "z=" tag) they don't, leading to signing failures on valid messages. Reported by James R. Marcus. Fix bug #SF2969700: Remember to NULL-terminate key data loaded from disk before using it. Don't use MAXHOSTNAMELEN as its value is unreliable. LIBOPENDKIM: Return an error from dkim_get_key_dns() if the query string is too big for a hostname buffer, rather than sending the truncated string to DNS anyway. LIBOPENDKIM: Ensure string termination in dkim_sig_getidentity() when calling dkim_qp_decode(). Patch from Stefan Schulze Frielinghaus. LIBOPENDKIM: In dkim_eom_sign(), don't change the handle's overall state before erroring out if the chunking state is invalid. BUILD: Fix bug #SF2969812: Don't install Lua sample files or man pages when "--with-lua" isn't specified. Patch from Kaspar Brand. BUILD: Fix bug #SF2965318: Don't define USE_LUA when LDAP is enabled. Problem noted by Guillaume Castagnino. LICENSE: Change from 4-clause BSD license to 3-clause BSD license. 2.0.0 (Eve) 2010/03/05 Feature request #SF2917224: Add optional OpenLDAP support. Feature request #SF2920389: Add CIDR support for IPv6 addresses. Feature request #SF2937428: Add "ExemptDomains" configuration item. Add optional Lua support, which enables a few script hooks for fine-grained policy controls when signing and verifying, and "miltertest", a new Lua-based scripting tool for exercising milter applications. Add "-Q" command line switch, putting the filter in query test mode to exercise the database code. Don't overwrite the signature verification status with that of the policy query status, leading to spurious "bad signature data" entries in the log. Problem noted by Roman Gelfand. Fix database query order for PeerList, InternalHosts, etc. so that negation works properly again. Fix crash-on-shutdown bug related to the crypto utilities functions. Drop "KeyList" in favour of "KeyTable" and "SigningTable" in the configuration file. See the opendkim.conf(5) man page for details. Also, "-K" has been dropped from the command line, meaning multiple key support now requires use of the configuration file. Fixes in DB walk code for DB 1.85. Fix bug #SF2936499: Clean up numerous compiler warnings. Fix bug #SF2951494: Improve logic for doing ADSP queries and reporting their results. Fix bug #SF2961161: dkim_sig_getidentity() could return successfully even if the provided buffer was too small to accept the decoded value. Reported by Ale Vesely. LIBOPENDKIM: Adjust dkim_sign() to accept base64-encoded DER private keys as well as PEM-formatted keys. LIBOPENDKIM: Several performance optimizations yielded from gprof data. LIBOPENDKIM: Fix a length computation that caused an invalid snprintf() call. From a Gentoo bug reported by Tilman Giese. LIBOPENDKIM: Fix compiler complaint about multiple definitions of global variables. Reported by Maarten Oelering. LIBOPENDKIM: Have dkim_eom() process all signatures instead of stopping after finding one good one. Also add library flag DKIM_LIBFLAGS_VERIFYONE, causing dkim_eom() to short-circuit after finding one good signature while verifying (i.e. reproducing the pre-2.0.0 behaviour). LIBOPENDKIM: Feature request #SF2961427: Add dkim_libversion(). Requested by Ale Vesely. TOOLS: Add "opendkim-genzone" which generates a BIND zone file fragment based on a KeyTable that contains all of the public keys required to match the configured private keys. BUILD: Add "--enable-codecoverage" to add build steps that generate profiling or code coverage reports when running unit tests. BUILD: Compile opendkim-testadsp with pthread libraries in case "--enable-arlib" was specified. BUILD: Fix an m4 quoting error that had rendered "--enable-debug" useless. BUILD: Check for functions upon which libmilter depends. Reported by Cyro Lord. PORTABILITY: Support for OS X from Bob Halley. 1.2.2 2010/01/19 Fix bug #SF2916729: Fix crash when reporting on multiple signatures, one of which was invalid in some way leaving its DKIM_SIGINFO only partially populated. Problem noted by Ryan Burchfield. Fix bug #SF2919365: A _SOCK_ADDR is just a (struct sockaddr) which isn't big enough for IPv6 addresses. Use a (struct sockaddr_storage) instead. Problem noted by Werner Wiethege. Fix initalization and processing of ODBX requests. Fix DB get operations for Sleepycat versions prior to 2.0.0. Set a flag when crypto initialization is done so that cleanup occurs on shutdown. Problem noted by Deiva Shanmugam. BUILD: Fix bug #SF2932392: Restore proper function of "--without-milter". Reported by Mark Sidell. 1.2.1 2009/12/23 Fix a disconnect in configuration regarding "On-KeyNotFound". Fix a type mismatch in dkimf_db_open() with respect to Sleepycat version 2 libraries, and a bug in dkimf_db_walk() with respect to Sleepycat version 1 libraries. Report _FFR_REPORT_INTERVALS in "-V" output. LIBAR: Tidy up some compile-time warnings. BUILD: Correct name of "bodylength_db" feature. BUILD: Define VERIFY_DOMAINKEYS in build-config.h when "--with-domainkeys" is enabled. BUILD: Define USE_DB in build-config.h when "--with-db" is enabled. 1.2.0 2009/12/08 Feature request #SF2873902: Overhaul the database backend code so that features that use external files or databases can be in any of several supported formats. This will make adding new external data sources and formats simpler, and obviates the need for a bunch of individual feature requests. This may have a few backward compatibility issues with respect to the configuration file. Feature requested by Daniel Black. Feature request #SF2873900: Add optional support for OpenDBX for connecting to ODBC and SQL backend databases. Requested by Daniel Black. Add "On-PolicyError" setting, allowing continuation of processing when an ADSP query fails. Activate _FFR_MULTIPLE_SIGNATURES, allowing optional addition of more than one signature per message passing through the filter. Add _FFR_RESIGN which allows binding of a signing handle to a verifying handle so that only one body hash needs to be run when a message will be re-signed as-is. Suggested by Daniel Black. LIBOPENDKIM: Move VBR functions from libopendkim into their own new library, libvbr. LIBOPENDKIM: Rename the rfc2822_*() parsing functions to have "dkim_" prefixes, and rename their containing file accordingly. LIBOPENDKIM: Fixes in relaxed body canonicalization and chunk processing. Problems noted by Masumi Taketomi Parekh of Yahoo!. LIBOPENDKIM: New library flag DKIM_LIBFLAGS_BADSIGHANDLES which asks the library to tolerate signature syntax errors and make such signatures available for limited inspection rather than completely ignoring them. Requested by Masumi Taketomi Parekh of Yahoo!. BUILD: Split up library assignments between libopendkim and opendkim, taking advantage of libtool. Based on a patch by Daniel Black. BUILD: When possible, limit the symbols exported as part of libopendkim to only those listed in dkim.h. BUILD: Generate opendkim.conf.5 man page containing all features, including FFR, annotated with if they are included and their experimental status (for FFRs). BUILD: Improve static linking against openssl as noted by Roman Gelfand. Compiles against openssl version 1.0.0-beta4 now. BUILD: Provide pkg-config files {opendkim,vbr,ar}.pc for use by other applications. BUILD: Fix up libresolv detection. BUILD: Add pkg-config checks for openssl, tre and opendbx packages to determine their installed library locations. Automate versioning and deployment. BUILD: Added m4 macro library directory with updated ax_pthread.m4. BUILD: Moved feature, _FFR and library #defines from Makefiles to build-config.h. Added macros for FFR and FEATURES. BUILD: Add support for versions of libtre older than 0.8.0. BUILD: Move all libopendkim tests into their own subdirectory. 1.1.2 2009/11/01 Under _FFR_SENDER_MACRO, need to check the value of "SenderMacro" in the configuration file. Noted by Daniel Black. Feature request #SF2873901: Add _FFR_REDIRECT which optionally redirects messages that fail verification to a specific address, storing the original recipients in X-Original-Recipient: header fields. Suggested by Daniel Black. LIBOPENDKIM: Have dkim_dns_set_callback() return DKIM_STAT_NOTIMPLEMENT if the underlying resolver doesn't have a callback facility. Suggested by Daniel Black. LIBOPENDKIM: Move internal-only types and macros from dkim.h to dkim-internal.h. Based on an idea from Daniel Black. LIBOPENDKIM: Add in all previously optional functions so that the API is invariant regardless of selected features. Add dkim_libfeature() as a way to detect availability of features at runtime. Suggested by Daniel Black. LIBOPENDKIM: Some global namespace consolidation. Suggested by Daniel Black. BUILD: Fix bug #SF2882206, patch #SF2880986: Handle libtre installations where "--enable-system-abi" was selected. Reported by Stevan Bajic; patch from Daniel Black. BUILD: Convert libar compilation to the libtool method. Suggested by Daniel Black. BUILD: Minor autoconf fixes, contributed by Daniel Black. 1.1.1 2009/10/09 Plug a number of potential but minor memory and file handle leaks, remove some dead code, guard against NULL dereferences, fix an errant return code check, fix a double-free(), and several other fixes found by a code analysis tool, used by courtesy of Cloudmark. Change "x-dkim-adsp" to "dkim-adsp" in Authentication-Results header field code now that RFC5617 is published. Apply "On-DNSError" setting when policy queries fail. BUILD: Some compilation fixes and type cleanup. Based on patches provided by Daniel Black. Add _FFR_SENDER_MACRO: Determine the message sender based on the contents of a macro instead of on a header field. Based on a patch from Ondrej Sury. 1.1.0 2009/09/16 Feature request #SF2839110: Add _FFR_IDENTITY_HEADER, to set an identity (i=) for signing based on the value found in a particular header. Requested by Florian Sager. Fix inside dkimf_libstatus() to return extended status code 4.7.5 if temp-fail is due to key retrieval failure. Fix bug #SF2831720: Use new dynamic signature header generation code (see below). Add new exception handling code "keynotfound" (short form "key") and "On-KeyNotFound", which handles keys not found in DNS separately from other DNS errors. Fixes inside dkimf_libstatus() so that SMTP reply codes get set properly for temp-fails. Remove _FFR_COMMAIZE. LIBOPENDKIM: Add dkim_getsighdr_d(), a dynamic-length version of dkim_getsighdr(). The old function interface remains unchanged for backward compatibility. LIBOPENDKIM: Add dkim_dstring_printf(). LIBOPENDKIM: Fix bug #SF2839858: Change "default_senderheaders" list to include only "from", per RFC5617. Problem noted by Erik Lotspeich. Activate _FFR_SENDER_HEADERS, adding "SenderHeaders" to the configuration file. BUILD: Fix bug #SF2841499: Fix building of opendkim tools so that they link against libdb when necessary. BUILD: Fix building of libopendkim/t-test115 so it agrees with what SHA methods are found by libopendkim itself. BUILD: Don't bother building libar unless --enable-arlib is specified. 1.0.0 2009/08/14 Initial release after code fork from dkim-milter package (v2.8.3). Fix bug #SF2813077: Don't do anything other than deliver messages when "t=y" is present in the verifying key record. Problem noted by Jens Elkner. Fix bug #SF2835208: Set the signal mask earlier so that signals of interest aren't delivered to threads that can't handle them. Problem noted by Mike Markley. LIBOPENDKIM: Fix bug #SF2795523: Correct canonicalization problem when a CRLF is split across body chunks and consecutive blank line counting is in progress. Reported by Mark Martinec. TESTS: Fix bug #SF2813058: Fix t-test117 so it doesn't fail if the DKIM_TMPDIR environment variable is set. Problem noted by Jens Elkner. PORTABILITY: Fix bug #SF2813058: Fixes to t-test100 for Solaris 10 (64-bit). Patch from Jens Elkner. OpenDKIM-rel-opendkim-2-11-0-Beta2/RELEASE_NOTES.Sendmail000066400000000000000000001657311337314105200222000ustar00rootroot00000000000000 DKIM-MILTER RELEASE NOTES This listing shows the versions of the dkim-milter package, the date of release, and a summary of the changes in that release. Bug and feature request (RFE) numbers that start with "SF" were logged via Sourceforge (http://www.sourceforge.net) trackers. Those not so labeled were logged internally at Sendmail, Inc. 2.8.3 2009/05/31 Close the configuration file after reading it, plugging a descriptor leak. Release memory associated with old configuration nodes (i.e. strings) as well as the nodes themselves. Connect the configuration handle to its allocated data so cleanup can actually be thorough. Fix an error message reported inside _FFR_REPLACE_RULES. Plug a memory leak in mlfi_header() tripped when errors occur. Since ADSP has not yet been registered by IANA, adjust its method label in Authentication-Results accordingly. Include selector, domain and other text if possible when logging key retrieval failures. Add _FFR_SENDER_HEADERS, allowing user control over which header fields are used to make the sign/verify decision and perform key selection. LIBDKIM: Initialize canon_lastchar in dkim_add_canon(). LIBDKIM: Clean up any compiled regular expressions in dkim_close(). LIBDKIM: Fix some type-related compiler warnings. 2.8.2 2009/02/17 Request a signature with an "i=" tag if signing for subdomains and a keylist entry matches. Previously this only occurred when using an explicit domain list. Problem noted by S. Moonesamy of Eland Systems. Fixes in and around dkim_socket_cleanup(). Problem noted by S. Moonesamy of Eland Systems. LIBDKIM: When logging a d2i_PUBKEY_bio() or EVP_PKEY_get1_RSA() failure, also log the selector and domain involved so manual diagnostics are possible. LIBDKIM/LIBAR: Feature request #SF2380508: Add new test for WITHOUT_LIBSM which removes references to libsm's sm_strl*() functions, so that libdkim and libar can stand on their own on systems which provide the strl*() functions. Requested by Frederik Pettai. LIBDKIM: Report DKIM_STAT_NOSIG if the caller commands that all signatures should be ignored. LIBDKIM: Plug a memory leak caused when responding to a malloc() failure. LIBDKIM: New signature error code DKIM_SIGERROR_KEYDECODE, used if d2i_PUBKEY_BIO() or EVP_PKEY_get1_RSA fails in dkim_sig_process(). LIBAR: Make reference to the "_res" structure more thread-safe. BUILD: Make use of conf_dkim_filter_ENVDEF since site.config.m4.dist refers to it. Problem noted by S. Moonesamy of Eland Systems. 2.8.1 2009/01/16 LIBDKIM: Fix bug #SF2508602: Add a translation string for DKIM_SIGERROR_KEYREVOKED and fix dkim_eom_verify() so it returns DKIM_STAT_REVOKED when appropriate. Problem noted by Mike Markley of Bank of America. 2.8.0 2009/01/08 Add configuration option "EnableCoredumps" which makes an explicit kernel request for cores on crashes. Currently only meaningful on Linux. Add configuration option "AuthServID" which sets the "authserv-id" token to use when generating Authentication-Results header fields. Report "fail" instead of "hardfail" on authentication failures, in compliance with the Authentication-Results: draft. Add _FFR_REPORT_INTERVALS, experimental support for the "ri" tag extension to DKIM policy and key records for specifying reporting intervals. Feature request #SF1985886: Add _FFR_MULTIPLE_SIGNATURES, allowing one instance of the filter to add multiple signatures. Suggested by Dave Crocker. Add "TemporaryDirectory" configuration file option for requesting that libdkim use an alternate directory for creating temporary files, and "KeepTemporaryFiles" for requesting that libdkim not delete those files for debugging purposes. Add optional support for the "unbound" asynchronous resolver library as it is DNSSEC-aware. Adds four new configuration file items: "BogusKey", "BogusPolicy", "InsecureKey" and "InsecurePolicy". Also add dkim_sig_getdnssec() and dkim_policy_getdnssec() to libdkim so callers can tell what the DNSSEC evaluation result was for each query. Based on a patch from John Dickinson. Add "BaseDirectory" configuration file option for specifying the desired current directory of the process. Make use of the key and policy "rs" tag, if present, when doing SMTP rejections. Use MTA macro "$j" as the hostname in generated reports instead of the output of gethostname() since on some systems the latter may not be fully-qualified. Remove ANTICIPATE_SENDMAIL_MUNGE, replacing it with a runtime check for the milter v2 feature which suppresses the addition of spaces in headers. Add _FFR_COMMAIZE which attempts to predict the reformatting the MTA will do to certain header fields to reduce verification failures. Add _FFR_DKIM_REPUTATION enabling a function used to query an open DKIM reputation service regarding the signing user and signing domain. The service's URL is http://www.dkim-reputation.org. (EXPERIMENTAL) Fix preloading of configuration defaults. Fix bug #SF2236040: Quote all of the POSIX regular expression special characters, not just some of them. Reported by Mark Martinec. When possible, log the selector and domain of the signature evaluated along with any errors in the libcrypto stack. LIBDKIM: Add "smtpbuf", "smtplen" and "interval" parameters to dkim_sig_getreportinfo() and dkim_policy_getreportinfo(). Also, remove the assertion that "addr" be non-NULL. LIBDKIM: Add DKIM_LIBFLAGS_ACCEPTDK which enables compatibility with DomainKeys-formatted key records. LIBDKIM: Adjust signature formatting for legibility. LIBDKIM: Check return status from dkim_canon_getfinal() to avoid bad dereferences. Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Render the DKIM handle unusable in dkim_eoh_sign() if a required header was absent. Activate _FFR_REQUIRED_HEADERS. 2.7.2 2008/09/02 Avoid memory leaks and infinite loops when releasing thread-specific memory. Reported by Jeff Earickson. 2.7.1 2008/08/27 Set up required callbacks for OpenSSL thread-safety. Problem noted by Zbigniew Szalbot. Disallow empty "t=" and "x=" tags. Return DKIM_STAT_KEYFAIL for various DNS key retrieval failures instead of DKIM_STAT_INTERNAL. 2.7.0 2008/07/23 Update to draft-ietf-dkim-ssp-04. In doing so, rename "ASPDiscard" to "ADSPDiscard", "ASPNoSuchDomain" to "ADSPNoSuchDomain" and "SendASPReports" to "SendADSPReports" in the configuration file. Feature request #29738: Add "TrustSignaturesFrom" configuration file item allowing fine-grained control over third-party signature handling. Feature request #SF2018848: Add "LocalADSP" feature allowing policy assertions from domains known to have specific policies but which don't publish ADSP records. Suggested by Bruno Kraychete da Costa. LIBDKIM: Fix an off-by-one overrun check in key and policy record decoding. Problem noted by John Dickinson. 2.6.0 2008/06/11 Remove "signaturemissing" as an old-style configuration action as it has been superseded by "ASPDiscard" and related functions. Add "SendASPReports" configuration option which generates ASP failure reports if requested by the sending domain. Update report generation for verification failures to use the new Abuse Reporting Format (ARF) and DKIM Reporting draft proposals. Add "MustBeSigned" configuration option, requiring signatures to cover specific headers if present. Rename "UseASPDiscard" to "ASPDiscard". Add "ASPNoSuchDomain" configuration option which rejects mail that appears to come from nonexistent domains as reported by the Author Signing Practises check. Add "ReportAddress" configuration option, used for defining the From: header of reports mailed out. Yet another compatibility fix with respect to Sleepycat DB. Fix processing of "LogWhy" configuration parameter. Problem noted by Erik Lotspeich. Add "-n" command line flag which parses the command line arguments and configuration file(s), then exits with an appropriate status code. Report DKIM and ASP results separately via the same Authentication-Results header field. Previous versions would alter the DKIM result based on ASP. Fix bug #SF1976931: Restore function of "nosignature" old-style action configuration, connected to "AlwaysAddARHeader". Problem noted by Lucas Brasilino. Feature request #SF1940233: Add "DontSignMailTo" configuration option, allowing a list of recipient patterns whose mail should not be signed. Requested by Don Hughes. LIBDKIM: Rename dkim_reportinfo() to dkim_sig_getreportinfo(), and add dkim_policy_getreportinfo(). LIBDKIM: Add several more signature error codes covering various key-related errors. LIBDKIM: Add dkim_sig_hdrsigned() utility, DKIM_OPTS_MUSTBESIGNED option, and DKIM_SIGERROR_MBSFAILED error code. LIBDKIM: Fix a bug in the computation of the result for dkim_canon_minbody(). LIBDKIM: Report corrupted base64 chunks instead of quietly tolerating them. LIBDKIM: Tidy up the cleanup code in dkim-canon.c. LIBDKIM: Properly handle "tag=" at the end of a data set (i.e. the tag exists and has an empty value). LIBDKIM: Use larger unsigned data types in dkim_sig_future() as was done elsewhere. LIBDKIM: Always populate a DKIM_SIGINFO with domain and selector before there's an opportunity for other parsing short-circuits. LIBDKIM: Fix bug #SF1984685: Remove the "margin" parameter from dkim_getsighdr(); make it controlled by a new function, dkim_set_margin(), so that the signed copy and the user-requested copy are identical. Activate _FFR_AUTHSERV_JOBID. 2.5.5 2008/04/25 Fix bug #SF1947301: Close up a logic problem in "UseASPDiscard" handling which could cause false rejections of mail from domains advertising "discardable" policies. Problem noted by Doug Kingston. LIBDKIM: Another compatibility fix with respect to Sleepycat DB. 2.5.4 2008/04/17 Skip signatures with errors in dkimf_authorsigok(). Avoid a NULL dereference in dkimf_config_reload() when starting without a configuration file. Fix an alignment problem in dkimf_checkip(). Problem reported by Jeff A. Earickson. LIBDKIM: Fix bug #SF1942387: Per RFC4871, disallow "l=" values that exceed the size of the canonicalized message body. 2.5.3 2008/04/14 Add "AllowSHA1Only" configuration option which permits operation of verifiers that only know about SHA1. Without this, a filter compiled with only SHA1 support will refuse to start in verifier mode. Add "LogWhy" configuration parameter and "-W" command line flag to request detailed logging about why a message was not signed by the filter. Intended for debugging; not intended for normal operation. Another tweak to parameters passed to db->open(). Based on patches from Jukka Salmi and S. Moonesamy. Fixes in ares_parse() to match the current syntax. In particular, deal with the fact that some of our tokens can legally appear in e-mail addresses. Problem noted by S. Moonesamy of Eland Systems. LIBDKIM: Evaluate key granularity against the "i=" value rather than the value of the From: header per RFC4871. Problem noted by Jason Long. LIBDKIM: Remove the chartable stuff from dkim-tables.c as it is not used anywhere. LIBDKIM: Fix bug #SF1940302: Perform stronger validation of the value of the "h=" tag. 2.5.2 2008/03/28 Preserve the sender's domain name outside of mlfi_eoh() as it's now needed in mlfi_eom(). Problem noted by Andy Fiddaman. Fix bug #SF1921873: Pass "-K" command line switch into the new configuration handling code. Problem noted by Al Smith. TOOLS: Fix flags portion of the TXT record output by dkim-genkey. Problem noted by Michael Carland. BUILD: Fix bug #SF1922422: Fix linker problems when POPAUTH is defined. 2.5.1 2008/03/20 Update for draft-kucherawy-sender-auth-header-14. Fix bug #SF1911328: Restore proper behaviour of SignHeaders and OmitHeaders, broken in the prior release's configuration overhaul. Problem reported by Jason Molzen. Fix bug #SF1912332: Fix parameters passed to db->open(). Problem reported by Tony Earnshaw. Fix bug #SF1912569: Initialize mutexes before entering test mode. Patch from Kaspar Brand. LIBDKIM: Add "subject" to "should_signhdrs" per RFC4871 section 5.5. LIBDKIM: More boundary checking fixes in dkim_canon_selecthdrs(). Problem noted by Warren Horvath. LIBDKIM: Fix bug #SF1820084: Return DKIM_STAT_MULTIDNSREPLY if a DNS query returns multiple records. 2.5.0 2008/03/06 Add "AutoRestartCount" and "AutoRestartRate" configuration parameters to limit runaway restart loops. Feature request #SF1735573: Add "AlwaysAddARHeader" option, which will add an Authentication-Results of "none" for unsigned messages from domains without a "strict" policy. Feature request #SF1807748: Reload the configuration file on receipt of SIGUSR1. Requested by Florian Sager. Feature request #SF1811969: Add _FFR_BODYLENGTH_DB which adds a "BodyLengthDBFile" feature, allowing a per-recipient decision on whether or not to use an "l=" tag when signing. Patch contributed by Daniel Black. Feature request #SF1841955: Add an "Include" facility to the configuration file. Feature request #SF1876941: Make the syslog facility selectable. Based on a patch from Jose-Marcio Martins da Cruz of Ecole des Mines de Paris. Feature request #SF1876943: Add _FFR_AUTHSERV_JOBID allowing the job ID to be included as part of the "authserv-id" in Authentication-Results: headers. Based on a patch from Jose-Marcio Martins da Cruz of Ecole des Mines de Paris. Feature request #SF1890581: Attempt to clean up a UNIX domain socket in the non-AutoRestart case as well. Requested by Daniel Black. Add "MilterDebug" configuration file option for requesting debugging output from the filter. Add "FixCRLF" configuration file option which activates the DKIM_LIBFLAGS_FIXCRLF flag (see below). Update to draft-ietf-dkim-ssp-03. In doing so, rename the "UseSSPDeny" configuration option to "UseASPDiscard". Handle an error from dkim_getsighdr() properly in mlfi_eom(). When VERIFY_DOMAINKEYS is active, don't short-circuit mlfi_eoh() between dk_verify() and dk_eoh() or a segmentation fault below dk_body() could result. LIBDKIM: Feature request #SF1823059: Export key, signature and policy syntax checking capability via the API. Based on a patch from Chris Behrens of Concentric Network Corporation. LIBDKIM: Assert defaults for "c" and "q" tags when parsing signature headers. Patch from Chris Behrens of Concentric Network Corporation. LIBDKIM: Better handling of truncated DNS replies; instead of just giving up if the "tc" (truncated) bit is set in the reply, see if there was enough of a reply returned to be able to complete the request. LIBDKIM: Fix recycling bug in header canonicalizations which was causing signatures other than the first one to fail in most cases. LIBDKIM: Add new dkim_chunk() interface. LIBDKIM: Enforce DKIM_OPTS_QUERYMETHOD library option even if there were no valid signatures. LIBDKIM: New DKIM_LIBFLAGS_FIXCRLF which requests that "naked" CRs and LFs be converted to CRLFs during canonicalization when signing. LIBDKIM: Fix bounds checking in dkim_canon_selecthdrs(). LIBAR: Eliminate a possible race condition in ar_dispatcher(). LIBAR: Timeouts passed to select() can't be bigger than 10^8. Problem noted by S. Moonesamy of Eland Systems. BUILD: Feature request #SF1876242: Install the filter in EBINDIR and everything else in UBINDIR. 2.4.4 2008/01/25 In mlfi_close(), don't assume the libmilter private context pointer is not NULL. Fail to start up if told to load a key list which resulted in no keys being loaded. When "AutoRestart" is in use, the parent will now wait for the child to terminate before exiting. Thus, something that signals the process ID in the pid file can also wait on that process to be gone before being sure that the service has actually shut down. Include the job ID when logging about Authentication-Results: headers that can't be parsed. Problem noted by S. Moonesamy. LIBDKIM: In dkim_policy(), skip invalid signatures during evaluation of step 1 of SSP as the signature handle may not have been fully populated. 2.4.3 2008/01/18 Request addition of an "i=" tag in the signature when signing for subdomains. Patch from Alin Nastac. TOOLS: Fix bug #SF1867259: "echo -n" is not portable. Problem noted by Gary Mills. TOOLS: Fix bug #SF1867869: Output of the "t=" value was incorrect with respect to the "s" flag. Reported by Geoff Adams. LIBAR: Further handling of the absence of "nameserver" lines in resolv.conf, this time in the manual processing code. LIBDKIM: Fix bug #SF1867839: 64-bit portability in rfc2822.c. Patch from Geoff Adams. LIBDKIM: Tighten up correctness of the first SSP test ("valid originator signature") in dkim_policy(). Problem noted by Alin Nastac. LIBDKIM: DKIM_SIGINFO handles are now initialized with an error code of DKIM_SIGERROR_UNKNOWN. The code only becomes DKIM_SIGERROR_OK after the cryptographic verification code returns a success result. BUILD: Fix bug #SF1818906: Update site.config.m4 to include a flag for installing libdkim when compiling static libraries, and installing dkim.h in either case. Requested by Chris Behrens of Concentric Network Corporation. 2.4.2 2008/01/02 Remove "-H" from the usage message. It was meant to be a command line interface to "AlwaysSignHeaders" but was never implemented. Problem noted by Jeff Anton. LIBDKIM: Make dkim_islwsp() into a macro to drastically reduce the number of function calls made during canonicalization. LIBDKIM: Fix bug #SF1857484: Fix logic problem in dkim_policy() with the new pstate checks. Problem noted by Werner Wiethege; patch from Chris Behrens of Concentric Network Corporation. 2.4.1 2007/12/20 Update for latest Authentication-Results: header draft. Avoid a NULL dereference in dkim_get_key(). Problem noted by Chris Behrens of Concentric Network Corporation. Fix bug #SF1842970: Make the overall header byte count check configurable, and increase the default. Also, add "On-Security" (configuration file) and "security" (command line) options for controlling the default reaction to such conditions. While we're at it, add an "On-Default" and "default" option for making a global action setting. Requested by Mark Martinec. LIBAR: Fix bug #SF1852618: Handle default case of no "nameserver" lines in /etc/resolv.conf. Problem noted by Mike Markley of Bank of America. LIBDKIM: Fix bug #SF1824876: Add "dkim_pstate" and make dkim_policy() re-entrant. Requested by Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1843733, SF1843782: Tighten up header name matching in dkim_get_header() and dkim_get_sender(). Patches from Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1843788: Fix an off-by-one length bug in dkim_header(). Patch from Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1850973: Remove MAXHDRCNT; make the arrays it previously defined dynamic. Reported by Mike Markley of Bank of America. LIBDKIM: Feature request #SF1841974: Numerous performance enhancements from Chris Behrens of Concentric Network Corporation. 2.4.0 2007/11/30 Take advantage of some more features that were introduced with milter v2 in sendmail 8.14.0: o If all canonicalizations are satisfied in terms of length limits, advise the MTA to stop sending the message body to reduce unneeded I/O. o Turn off as many unnecessary SMTP protocol steps as possible. o Fail option negotiation if any of the milter features required are not available. o If specific MTA macros are to be used for making the sign vs. verify decision, explicitly request them. Prevent corruption in Authentication-Results: headers caused by signatures that have explicit "i=" values. Report "hardfail" instead of "fail" on authentication failures, in compliance with the Authentication-Results: draft. Amend the "-M" command line option and "MacroList" configuration options to allow a list of possible values for each macro. Add _FFR_SELECTOR_HEADER, adding the means to choose which selector (and thus which key) is used to sign based on the value found in a particular header. Requested by Steve Jones of Bank of America. Add dkimf_dstring*() (dynamic string) functions and clean up some code by making use of it. Skip all the userid and group changes when either "-u" or "UserID" is in use if the requested user is the same as the executing user. Fix use of "UseSSPDeny" to include handling of unsigned messages. Fix bug #SF1834701: Log a warning and temp-fail the message if a key list is in use that didn't match the sender for a message which should be signed. Problem noted by Jim Hermann. Patch #SF1796697: Add _FFR_REPLACE_RULES, adding the facility to do substring replacement before signing to anticipate things like the MTA "masquerade" and "genericstable" functions. Requires further development. Replace "gentxt.csh" with more robust "dkim-genkey" utility. Feature request #SF1811962: Add new utilities "dkim-testkey" which verifies that a public key is readable and properly formatted and matches the locally-provided private key, and "dkim-testssp" which retrieves a domain's sender signing practises record and prints it in a human-readable form. Based on code contributed by Daniel Black. Feature request #SF1817253: Add "UMask" configuration file option. Suggested by Daniel Black. Feature request #SF1818863: Add a section to site.config.m4.dist to request a build of the shared object version of libdkim. Requested by Chris Behrens of Concentric Network Corporation. Feature request #SF1834748: Use a more meaningful SMTP reply when rejecting a message at the SMTP level due to SSP. Suggested by S. Moonesamy of Eland Systems. LIBDKIM: Return DKIM_STAT_NOKEY from dkim_get_key_dns() if the answer count comes back zero, rather than DKIM_STAT_CANTVRFY. Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Plug a memory leak in dkim_get_key(). Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Replace a dicey memcpy() call with memmove(). Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Add DKIM_CBSTAT_NOTFOUND and DKIM_CBSTAT_ERROR callback return codes, and DKIM_STAT_CBERROR return code. Suggested by Chris Behrens of Concentric Network Corporation. LIBDKIM: Add dkim_minbody() to determine how much more body text is required to satisfy canonicalizations. LIBDKIM: Add dkim_gethandlingstr() and dkim_getpolicystr() for translation of SSP handling and policy codes into printable strings. LIBDKIM: Add _FFR_PARSE_TIME, adding a utility function that can be used to detect that the timestamp on a signature and the value of the Date: header wildly differ. Incomplete. LIBDKIM: If a message comes in with no properly-formed sender headers, dkim_eoh() now renders the DKIM handle unusable by later data processing calls. LIBDKIM: Fix arithmetic in dkim_sig_expired(). LIBDKIM: In dkim_eoh_verify(), check for a NULL user pointer return from rfc2822_mailbox_split() (was previously only checking for an error code or NULL domain). Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1819489: Fix signature header name check in dkim_header(). Patch from Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1819559: Fix key granularity processing. LIBDKIM: Fix bug #SF1819571: More robust processing of "s=" in keys. LIBDKIM: Fix bug #SF1819607: Allow "t=" and "x=" values up to 64 bits since RFC4871 requires at least 40. LIBDKIM: Fix bug #SF1820017: Don't accept signatures with no "v=" tag. LIBDKIM: Fix bug #SF1820060: The value of "q=" may be a colon-separated list of values to parse. LIBDKIM: Fix bug #SF1820080: The value of "i=" may be quoted-printable so do appropriate decoding. LIBDKIM: Fix bug #SF1820123: "simple" body canonicalization must contain at least CRLF. LIBDKIM: Fix bug #SF1820370: More graceful handling of grossly malformed signature headers. Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1822287 and SF1822295: Update policy check code to use the draft-ietf-dkim-ssp-01 algorithm. Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1822329: In dkim_get_policy(), check for and handle error returns from the subordinate lookup functions. Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1822331: Use consistent return codes in dkim_get_policy_dns(). Problem noted by Chris Behrens of Concentric Network Corporation. LIBDKIM: Fix bug #SF1832703: When looking for headers to canonicalize during verification, disregard spaces between the header name and the colon (":") character. Problem noted by James Sargent of AOL. LIBDKIM: Fix bug #SF1838826: Several fixes with respect to processing key and policy flags. Problems noted by Marc Martinec. LIBDKIM: Feature request #SF1821005: Add dkim_getdomain(), an accessor function for dkim_domain. Requested by Chris Behrens of Concentric Network Corporation. Activate _FFR_QUERY_CACHE (Feature request #SF1675359) and _FFR_SELECT_SIGN_HEADERS. 2.3.2 2007/10/19 Fix bug #25896: Fix a bug in parsing of "RemoveARFrom". LIBDKIM: Fix a bug in the key reuse block of dkim_get_key() which assumed that a domain and selector match guaranteed a copied key and key tag list. LIBDKIM: Fix bug #SF1812687: Fix handling check in dkim_get_policy(). Patch from Daniel Black. 2.3.1 2007/10/12 Fix header loss problem in test mode. Fix bug #SF1808886: Handle missing or empty test inputs more gracefully. Based on a patch from Kaspar Brand. Fix bug #SF1808881: Check various integer conversions for negative, overflow or inappropriate values. Suggested by Kaspar Brand. Feature request #SF1809239: Restore performance of test mode on large messages. Requested by Kaspar Brand. Patch #SF1811132: Include in test.c for malloc() prototype. Patch from Daniel Black. BUILD: Patch #SF1810712: Correct default location for the Tre regular expression library. Suggested by Daniel Black. 2.3.0 2007/10/06 Add "UseSSPDeny" configuration option which causes the filter to reject messages which are determined to be suspicious according to the new draft-ietf-dkim-ssp-01, and whose sending domains advertise a recommended handling of "deny", and whose SSP records are not in "test" mode. Add "MaximumSignedBytes" configuration option limiting the number of bytes of the message body to be signed. Add "-t" command line option for reading an RFC2822-formatted message from a named file and attempting to evaluate it, "-F" command line option for using a fixed signing time, and "-v" command line option for requesting verbose output. Finally, new configuration option "StrictTestMode" asserts that all lines of input must be CRLF-terminated. Based on patches from Kaspar Brand. Add "TestPublicKeys" setting for instructing libdkim to read public keys from a file, for use during automated testing. Based on a patch from Jeff Barry. When using _FFR_QUERY_CACHE, periodically report cache activity statistics. Don't arbitrarily suppress signing of already-signed messages. Fix bug #25728: When "AutoRestart" is in use, try to remove the socket (if it's a UNIX domain socket) prior to trying to start the child. LIBDKIM: Add dkim_getmode() function. LIBDKIM: Fixes to policy evaluation in dkim_policy(). Based on a patch from Jeff Barry. LIBDKIM: Patch #SF1796687: Add DKIM_LIBFLAGS_ACCEPTV05 which causes the library to accept signatures with version strings of "0.5", i.e. those based on later versions of the DKIM draft specification. This does not change any other part of signature validation or canonicalization, only the version string test. Suggested by Jim Fenton of Cisco. LIBDKIM: When closing canonicalizations, flush the temporary files rather than closing them so that things like dkim_reportinfo() return useful descriptors. Close the temporary files in dkim_canon_free() only. Problem noted by Jeff Barry. LIBDKIM: Fix variable argument processing by merging dkim_error() and dkim_verror(). The previous code was causing segmentation faults on selected operating systems. Activate the following FFRs: _FFR_KEY_REUSE _FFR_SET_REPLY 2.2.1 2007/09/07 Insert VBR headers at the top rather than appending them to be sensitive to legacy DomainKeys operations. Patch from S. Moonesamy of Eland Systems. Discontinue use of MAXHOSTNAMELEN as the maximum size of a hostname since some vendors set it to 64 (maximum size of a DNS label) and some to 256 (maximum size of an FQDN). Instead, define and use DKIM_MAXHOSTNAMELEN (256). Problem noted by Jeff Barry. LIBDKIM: Rename and update the default_signhdrs and default_skiphdrs arrays to match what's in RFC4871 section 5.5 SHOULD and SHOULD NOT lists. LIBDKIM: Apply DKIM_OPTS_SKIPHDRS only when signing. LIBDKIM: Add missing entries to prv_results, and add a dkim_getresultstr() function for translating DKIM_STAT result codes. Patch from Kaspar Brand. Fix bug #SF1785624: Resolve build problem introduced in previous version when NETINET6 is in use. Reported by Andrew Benham. Fix bug #SF1786033: Resolve build problem introduced in previous version affecting later versions of Solaris. Reported by Andy Fiddaman. Fix bug #SF1787473: Initialize the default "-i" list properly (given changes made in the previous version) so that mail from localhost still gets signed. Reported by Graham Murray. 2.2.0 2007/08/30 Change format of the peerfile, internal and external host lists, etc. to allow exclusion entries. See the man page for additional details. Amend "-u" to include the ability to name a group into which the filter process should be placed. Feature request #SF1783155: Make keylist pattern matching case-insensitive. LIBDKIM: Handle CNAMEs properly when using the standard resolver. Problem noted by Jim Fenton of Cisco. LIBDKIM: Fix bug #SF1782076: Adjust signature header wrapping logic so that a "b=" against the margin gets wrapped consistently when signing and verifying. Reported by Kaspar Brand. 2.1.2 2007/08/22 LIBDKIM: At the end of dkim_eoh_verify(), don't overwrite any existing descriptive error text before returning on verification errors. Problem noted by Andy Fiddaman. LIBDKIM: Remove redundant assertion of length limits in dkim_canon_bodychunk(). The code in dkim_canon_write() has it correct, so use that instead. Problem noted by Mark Martinec. LIBDKIM: Fix bug #SF1777332: Fix "relaxed" body canonicalization. Some code from the older implementation was still present conflicting with the newer code. Reported by Andrey Chernov. 2.1.1 2007/08/13 Fix bug #SF1743896 (reopened): Don't crash if a From: header with no domain is found. Patch from Andy Fiddaman. LIBDKIM: Fix type mismatches regarding restricted lengths. Problems noted by Jukka Salmi. LIBDKIM: Fix bug #SF1771520: Return an error from dkim_policy() if the sender's domain name could not be determined. Patch from Andy Fiddaman. 2.1.0 2007/08/10 Update to new (draft version 06) Authentication-Results: header format. Do an SSP query for any message that didn't either succeed verification or cause some kind of internal error, not just those that failed to verify. Tighten up the logic used when checking header space allocation. LIBDKIM: Heavy cleanup of dkim_eoh() and dkim_eom() via patches from Chris Behrens of Concentric Network Corporation. LIBDKIM: Add more fine-grained state control enforcing the order in which the message processing functions are called. There was previously a hole which would allow, for example, more headers to be submitted after a call to dkim_eoh() if a prescreen callback returned a "tryagain" result. LIBDKIM: Add dkim_sig_getidentity(). LIBDKIM: Fix bug #SF1769270: Use the default query type to retrieve signing policy for unsigned messages. LIBDKIM: Fix bug #SF1769445: Return the correct policy result from dkim_get_policy_dns() rather than always returning an empty string. Patch by Andy Fiddaman. LIBDKIM: Amend dkim_sig_getcanonlen() to include a parameter which receives the signature length limit, if any. LIBDKIM: Restore proper value to dkim_bodylen. Problem noted by Jukka Salmi. LIBDKIM: Don't inexplicably clear sig_signalg. Problem noted by Jukka Salmi. Feature request #SF1761475: Add "ClockDrift" configuration option for tolerating out-of-synch clocks. Suggested by Kaspar Brand. Feature request #SF1761481: Add "SyslogSuccess" configuration option for logging successful operations rather than just errors or other informational messages. Suggested by Kaspar Brand. Feature request #SF1769888: Amend dkim_policy() to be able to return the policy type retrieved from the sending domain. Also add dkim_getpresult() and associated other code to get additional policy evaluation information. Requested by Andy Fiddaman. 2.0.2 2007/08/03 Fix bug #SF1766313: Make configuration handling 64-bit friendly. Other 64-bit portability issues also addressed. Problems noted by Chris Box. Add _FFR_DNS_UPGRADE which establishes a second libar instance in TCP mode for handling truncated UDP replies. Also make some minor fixes in the key and policy DNS lookup functions to provide more consistent handling of such responses. Problems noted by Kaspar Brand; code is still experimental. 2.0.1 2007/08/02 Fix bug #SF1760481: Make header space allocations fully dynamic rather that establishing compile-time per-header limits. There is still an overall cap, however. Suggested by Ralf Hildebrandt. LIBDKIM: Fixes inside _FFR_KEY_REUSE. 2.0.0 2007/07/27 Remove all support for versions older than RFC4871. Older statistics databases will not be incompatible with the new code since version information is no longer included in the record format. Add "Resent-Sender" and "Resent-From" to the list of headers checked to determine whether or not the message should be signed or verified. Report an authentication result of "permerror" when the message can't be verified for syntax or other non-crypto reasons. New configuration file item "RemoveARFrom" allows specification of hostnames/domains whose existing Authentication-Results: headers should be removed. Also add "RemoveARAll" which allows selection of whether all such headers should be removed or only those containing a DKIM result. New configuration file item "RemoveOldSignatures" deletes existing signatures when signing. Fix bug #SF1743896: Don't crash if a From: header with no domain is found. Patch from Andy Fiddaman. Fix bug #SF1743964: Remove the pid file on shutdown or startup failure. Patch from Mike Markley. LIBAR: Plug descriptor and memory leaks in ar_shutdown(). LIBDKIM: Rework _FFR_VBR code to prepare it for extraction into an independent library. LIBDKIM: The key and policy lookup callbacks must now return a DKIM_CBSTAT constant so that they can have their corresponding libdkim functions return DKIM_STAT_CBTRYAGAIN if desired. Suggested by Chris Behrens of Concentric Network Corporation. LIBDKIM: Add _FFR_DIFFHEADERS which adds dkim_diffheaders() to enable the caller to search for headers that may have been munged in transit thus causing a verification failure. LIBDKIM: Feature request #SF1473131: Overhaul data structures, functions and documentation to allow fine-grained handling of messages bearing multiple signatures. This included the following changes: o Extend draft-ietf-dkim-ssp-00 support to cover multiply-signed messags. o Introduce DKIM_SIGERROR type/constants for associating an error code with each individual signature. o New libary flag DKIM_LIBFLAG_DELAYSIGPROC delays all signature processing until dkim_eom(). o New libary flag DKIM_LIBFLAG_EOHCHECK causes dkim_eoh() to return an error if it was unable to find any valid signatures when verifying. o Add new DKIM_CANON data type, referring to a parallel canonicalization required for signature generation or verification. o New function dkim_getsiglist() retrieves an array of DKIM_SIGINFO handles referring to all of the signatures discovered on a message. o New function dkim_getsignature() retrieves a single DKIM_SIGINFO handle which is the one libdkim will use to return its final result. o New function dkim_sig_getflags() to retrieve flags attached to a signature handle after processing. o New function dkim_sig_geterror() to retrieve the error code associated with a signature handle after processing. o New function dkim_sig_getbh() to retrieve the body hash test result on a signature after processing. o New function dkim_set_final() sets a user-provided callback called by dkim_eom() to do any final processing the caller may desire. o New function dkim_sig_process() manually executes verification of a signature, for use from within the prescreen or final callbacks. o Rename dkim_getcanonlen() to dkim_sig_getcanonlen(), dkim_getsigntime() to dkim_sig_getsigntime(), dkim_getselector() to dkim_sig_getselector(), dkim_getsigndomain() to dkim_sig_getdomain(), dkim_getsignalg() to dkim_sig_getsignalg() and dkim_getkeysize() to dkim_sig_getkeysize() as they now act on a specific signature rather than on an entire message. o The user-provided key and policy lookup functions must now accept a DKIM_SIGINFO handle as an additional parameter. o dkim_reportinfo() and dkim_ohdrs() now also require a DKIM_SIGINFO handle as an additional parameter. LIBDKIM: Fix signal logic in dkim_cache_read_unlock(). Patch from Chris Behrens of Concentric Network Corporation. LIBDKIM: Add _FFR_KEY_REUSE which avoids doing duplicate key lookups if the same key is used on two signatures in the same message. Suggested by Chris Behrens of Concentric Network Corporation. LIBDKIM: Changed prototype for dkim_policy() to reflect the new code. Remove _FFR_FLUSH_HEADERS. The functionality it provided is now accessed via the new configuration options described above. Activate _FFR_HASH_BUFFERING. BUILD: More unit tests. 1.2.0 2007/06/26 Update sender signing policy (SSP) code to match the new draft-ietf-dkim-ssp-00 specification syntax. In doing so, remove _FFR_ALLMAN_SSP_02. If "-u" is specified, call initgroups() and setgid() as well. Reported by Mike Markley; based on a patch from S. Moonesamy of Eland Systems. Fix bug #SF1738354: Add "L" data to CMDLINEOPTS. Reported by Andrey Chernov. 1.1.0 2007/06/15 Add a new option to "-L" and "Minimum" allowing a specific maximum number of bytes of appended, unsigned text. Suggested by Philip Guenther. Documentation and build patches from Gregory Shapiro, and documentation patches from Steve Jones of Bank of America. Under _FFR_VBR, if dkim_vbr_query() returns an error, report the error and then don't add the header. Reported by S. Moonesamy of Eland Systems. Fix bug #24586: Allow "-?" just to get the usage message; also hint at such if the filter is invoked with no arguments. LIBDKIM: Define DKIM_STAT_CBTRYAGAIN and DKIM_CBSTAT_TRYAGAIN. BUILD: More unit tests. 1.0.0 2007/05/23 First release after DKIM issued as a standard (RFC4871). Remove the "-v" command line option and "Version" configuration file item, which permitted selection of the signing version. Remove "nowsp" canonicalization option. LIBDKIM: Define DKIM_VERSION_RFC4871 and make it the default signing version. LIBDKIM: Remove DKIM_CANON_NOWSP and DKIM_VERSION_ALLMAN_BASE_00 which defined it. Gradually, support for old versions will be phased out. 0.8.1 2007/05/22 Portability fixes for Solaris. LIBDKIM: Define DKIM_CBSTAT_* constants which are to be used as return values from callbacks. Also define new status values DKIM_STAT_CBREJECT and DKIM_STAT_CBINVALID indicating results from callbacks back to the calling applications. Suggested by James Sargent of AOL. LIBDKIM: Slightly nicer wrapping of "b=", "bh=" and "z=" in dkim_getsighdr(). LIBDKIM: Define callbacks with respect to the DKIM library handle rather than each signing/verifying instance. Suggested by James Sargent of AOL. BUILD: Reference libssl and libcrypto in dkim-filter/Makefile.m4 rather than in the template site.config.m4 file since it's always required anyway. BUILD: Fix man page entry in dkim-filter/Makefile.m4. 0.8.0 2007/05/17 Add a dkim-stats(8) man page. Contributed by Mike Markley. Add "SignatureTTL", "Diagnostics" and "AlwaysSignHeaders" options to the configuration file and man page. Add _FFR_ZTAGS for optionally saving diagonstic information when a signature fails if the signature contained a "z=" tag. Still more minor fixes in _FFR_STATS related to DB versions. Feature request #SF1473129: Split configuration file details into their own man page. LIBDKIM: Still more minor fixes in _FFR_QUERY_CACHE related to DB versions. Reported by Ben Lentz. LIBDKIM: Remove dkim_getidentity(), as the function it provides isn't part of DKIM. Instead, provide that functionality in dkim-filter. LIBDKIM: Add a new option DKIM_OPTS_ALWAYSHDRS which allows specification of a list of header names which should always be included in signature header lists whether or not the headers were actually present, preventing them from being added downstream before verification. LIBDKIM: Add a new option DKIM_OPTS_SIGNATURETTL which allows the caller to assert a time-to-live on signatures generated. This causes the "x=" tag to appear in signatures. LIBDKIM: Add a new library flag DKIM_LIBFLAGS_ZTAGS which causes signatures generated to include the original header set encoded for transport so the verifier can use it to diagnose verification failures. This causes the "z=" tag to appear in signatures. LIBDKIM: Add dkim_ohdrs() which extracts the sender's set of headers if a "z=" tag was present in the signature. This can then be used by the caller to diagnose verification failures for signatures which contain them. LIBDKIM: Add the first large (and yet not the smallest) change to support multiple signatures. There's now a method via a few callbacks to give the caller access to the signatures discovered by the end-of-headers callback. The caller can analyze the signatures, reorder them, or flag some to be ignored. After reordering, the library still simply runs with the first that appears to be syntactically valid; actual processing of multiple signatures after the re-ordering will be in an upcoming release. LIBDKIM: _FFR_QUERY_CACHE now only covers DNS key lookups, not all key lookups. LIBDKIM: Move the method-specific policy lookup functions into their own new files, dkim-policy.c and dkim-policy.h. LIBDKIM: Slightly nicer wrapping of "h=" in dkim_getsighdr(). LIBDKIM: Add dkim_set_signer() for specifying the message's signer for signature generation. BUILD: More unit tests. Activate the following FFRs: _FFR_QUARANTINE _FFR_REPORTINFO 0.7.1 2007/05/09 More minor fixes in _FFR_STATS related to DB versions. Based on a patch by Graham Murray. LIBDKIM: More minor fixes in _FFR_QUERY_CACHE related to DB versions. LIBDKIM: Use read-write locks instead of a mutex in _FFR_QUERY_CACHE when appropriate. LIBDKIM: When using _FFR_QUERY_CACHE with recent enough versions of the DB library, tell the library to use the same temporary directory as libdkim is using. BUILD: Fix bug #SF1715265: Correct a typo which caused libdkim to fail to build against the asynchronous resolver library. Reported by Andy Fiddaman. 0.7.0 2007/05/03 Several more fixes in _FFR_STATS related to DB versions. LIBDKIM: Add support for optional callbacks to do key and policy lookups using an API provided by the caller rather than using DNS directly. New functions dkim_set_key_lookup() and dkim_set_policy_lookup() set these callbacks. Also add dkim_getdomain() and dkim_getselector() utility functions so those callbacks can extract the data required to make the queries. Note that these will probably change slightly when support for multiple signatures is finally added. Suggested by James Sargent of AOL. LIBDKIM: Fix bug #SF1708756: Set dkim_partial earlier during signing so that the "l=" portion is included in the canonicalized signature header. Reported by Andrey Chernov. LIBDKIM: Algorithm and initialization fixes in policy retrieval found by the new unit tests. LIBDKIM: Several more fixes in _FFR_QUERY_CACHE related to DB versions. LIBDKIM: Fix bug #SF1706248: Rewrite dkim_getidentity() so it returns a more sane value for the sender in all cases. Another utility function will be added later for obtaining the signer's identity. Reported by Andrey Chernov. BUILD: Overhaul the build scripts so that all the user editing is done in devtools/Site/site.config.m4 rather than in each individual directory's Makefile.m4. Include a template for this purpose. BUILD: Begin a collection of automated unit tests. Activate the following FFRs: _FFR_LOG_SSL_ERRORS _FFR_MULTIPLE_KEYS _FFR_OMIT_HEADERS _FFR_QUERY_FILE _FFR_SET_DNS_CALLBACK (Feature request #SF1473171) 0.6.6 2007/04/25 Update _FFR_SELECT_CANONICALIZATION for split canonicalization methods. Add _FFR_STATS, creating an optional database for storing pass/fail statistics per domain over time, and a command-line tool for querying the database contents. Requires Sleepycat DB. LIBDKIM: Patch #SF1705155: Fixes in "relaxed" header canonicalization code. Problem noted by Ben Lentz. LIBDKIM: Add _FFR_HASH_BUFFERING, experimental code that adds a layer of buffering in front of dkim_canonwrite() so the SHA hashing functions are called less often. LIBDKIM: Only call dkim_flush_blanks() when it will actually do something. LIBDKIM: Fix bug #SF1706530: Call EVP_cleanup() in dkim_close(). Suggested by Andy Fiddaman. LIBDKIM: Inside _FFR_QUERY_CACHE, fix cursor operations when compiled against very old versions of Sleepycat DB. LIBDKIM: When opening the database with _FFR_QUERY_CACHE, make sure the library is allowed to create the database. 0.6.5 2007/04/20 Further fixes in POPAUTH code for backward-compatibility with older versions of Sleepycat DB. Memory corruption fixes inside _FFR_MULTIPLE_KEYS. Reported by S. Moonesamy of Eland Systems. Re-implement _FFR_OMIT_HEADERS using the new libdkim option (see below). Return DKIM_STAT_SYNTAX from dkim_eoh() if an empty "d", "s" or "b" tag is discovered on a signature. Export most internal header lists so callers can use them. Fix bug #SF1702708: Don't start in signing mode without at least one key and selector specified. Reported by Andrey Chernov. Feature request #SF1675359: Add _FFR_QUERY_CACHE, allowing optional caching on-disk of key and policy records retrieved via DNS to reduce the number of round trips to the nameserver. Requires Sleepycat DB. Requested by Jim Popovitch. Portability fixes for Solaris. LIBDKIM: Enforce mandatory headers in dkim_eoh(). LIBDKIM: Add dkim_close() for library shutdown. LIBDKIM: Add option DKIM_OPTS_SKIPHDRS to skip headers that should not be signed or verified. LIBDKIM: Initialize dkiml_fixedtime. 0.6.4 2007/04/16 Further fixes in POPAUTH code. Based on patches from John Merriam. Modify the output of "-V" further so it also includes active code options (as opposed to just FFRs). When linked against libdk, get additional forensic data from dk_geterror() whenever possible. Changes to _FFR_MULTIPLE_KEYS: Add a domain field in the file, and try a couple of filename extensions before giving up when reading private keys. Add more calls to dkim_error() for additional diagnostic information around the DNS queries. Fix bug #SF1700333: Remove the dkim_sig_signerok() check as it actually detects (and rejects) third-party signatures. The code is still there, just disabled, in case we want to use it after SSP addresses that question. Reported by James Sargent of AOL. Add _FFR_CAPTURE_UNKNOWN_ERRORS which quarantines jobs that cause unexpected results from dkim_eom() to allow more detailed analysis. LIBAR: Fix bug #SF1537476: Update to support IPv6 nameservers. 0.6.3 2007/04/06 Avoid deadlock errors in the POPAUTH code by protecting that code with a mutex as well. Also, "l_end" should be "l_len". Problems noted by John Merriam. Fix bug #SF1693248: Add support for sendmail 8.14.x and its "preserve leading spaces" option. Based on a patch from Andy Fiddaman. Fix bug #SF1693249: If dkim_eoh() returns DKIM_STAT_NOSIG and then the caller calls dkim_eom() to get policy (which the documentation says is acceptable), assertion failures were tripped because the SHA hash(es) weren't initialized and dkim_domain wasn't set. Reported by Andy Fiddaman. LIBDKIM: Add _FFR_QUERY_FILE for getting keys and policies from a flat text file rather than DNS for offline or automated testing. Based on a patch from Jeff Barry. LIBDKIM: New option DKIM_OPTS_FIXEDTIME to use a specific time when generating signatures, to be used for offline or automated testing. Based on a patch from Jeff Barry. LIBDKIM: Fix bug #SF1691659: Fix a type mismatch so that RSA_sign() returns reasonable results on 64-bit platforms. Reported by Andy Fiddaman. LIBAR: Fix bug #SF1694130: Block signals that should be caught and handled elsewhere, such as in libmilter. Patch by Andy Fiddaman. 0.6.2 2007/03/30 Don't start if you're in signing mode and no selector was chosen on the command line or in the configuration file. Don't start if the version of OpenSSL used to compile libdkim is not the same as the one used to compile the filter. Print the version of OpenSSL in use when "-V" is used on the command line. Add _FFR_VBR, enabling optional support for the Vouch By Reference domain reputation proposal. Add "BodyLengths" configuration file option which adds the "l=" parameter when signing messages so re-mailers (e.g. MLMs) which append text to the message won't interfere with successful verification. Fix bug #SF1689101: Fix a minor error in argv processing when _FFR_OMIT_HEADERS was in use. LIBDKIM: Change DKIM_SIGN_DEFAULT to point to "rsa-sha256" if it's available. LIBDKIM: Add dkim_ssl_version(). LIBDKIM: Fix bug #SF1681632: Fix a bug in header selection when signing. Messages verified just fine, but some headers could accidentally be omitted during signing. From a patch for bug #SF1541490 for dk-milter, reported by Mark Martinec; essentially the same bug existed in libdkim. 0.6.1 2007/03/07 Load the -C values from the configuration file if -C wasn't present on the command line. Previously, they were ignored. Fix bug #SF1477211: Add an appropriate Authentication-Results: header when a signature uses a hash which the matching key does not authorize. Feature request #SF1497802: Add _FFR_QUARANTINE, allowing optional quarantining of messages which fail verification or policy checks. Feature request #SF1605766: To reduce spurious logging, don't set mctx_status to DKIMF_STATUS_NOSIGNATURE unless the signature was missing on a message from a domain that claims it signs everything. LIBDKIM: Fix a verification version auto-detection bug that was causing some false negatives. LIBDKIM: Fix bug #SF1672787: Fix an additional corruption bug in dkim_getsighdr(). LIBDKIM: Select the correct signature to replay into canonicalization, rather than always using the first one. Problem noted by James Sargent of AOL. 0.6.0 2007/03/01 Bring up to currency with "ietf-base-10" which is probably the version that the IETF will issue as an RFC. This includes: - signature "q=" option delimiter is now "/", and the default value is now "dns/txt" - if both "t=" and "x=" are present in a signature, make sure the former is less than the latter - disregard signatures that appear to have been generated in the future - support for draft and final versions of "v=" tags in both keys and signatures Activate _FFR_VERIFY_DOMAINKEYS. Complete support for DKIM_QUERY_FILE for use in debugging and testing. Fix a number of minor bugs in signature header generation which could cause corruption and thus validation and/or syntax errors. Fix bug #SF1507535: Fix an FFR-related build issue. Reported by Frederik Pettai. Patch #SF1505401: Add _FFR_OMIT_HEADERS, copied from dk-milter. This will probably be replaced later by an extension to dkim_options(). Patch provided by Ben Lentz. LIBDKIM: Fix bug #SF1512860: Before returning DKIM_STAT_NOSIG from dkim_eom(), try to retrieve the sending domain's policy. LIBDKIM: Fix bug #SF1608314: Fix processing of config file items "Userid" and "Mode". Patch from John Villalovos. LIBDKIM: Add dkim_geterror() to retrieve additional diagnostic data from the API when a function call returns DKIM_STAT_INTERNAL or something else whose cause isn't readily apparent. LIBDKIM: Remove an extraneous pointer type in the parameter list for dkim_sign(). Reported by Jeff Barry. 0.5.2 2006/09/18 Fix bug #SF1537905: If necessary, try again to get the job ID in mlfi_eom() in case it came down later than expected (e.g. postfix). Suggested by Mark Martinec. Fix a couple of minor build problems. Fix bug #SF1559406: Change MAXHEADER to 4096. LIBDKIM: Fix bug #SF1544301: Fix an issue with processing a message which has trailing spaces on its last line. Reported by Mark Martinec. LIBDKIM: Fix bug #SF1558014: Confirm the body hash in the signature matches the actual body hash when verifying. Reported by Mark Martinec. LIBDKIM: Add preliminary support for the draft-allman-dkim-ssp-02 specification as _FFR_ALLMAN_SSP_02. LIBAR: Adapt to the post-bind4 resolver API. Problem reported by S. Moonesamy of Eland Systems. 0.5.1 2006/06/14 Add compile-time option _FFR_ANTICIPATE_SENDMAIL_MUNGE which attempts to replicate some header rewriting the sendmail MTA will do, which otherwise prevents signature validation from succeeding. Problem noted by Ken Jones. Add support for "ietf-base-02" signing mode (which is really synonymous with "ietf-base-01"). LIBDKIM: Report a syntax error when a signature header arrives with any required fields missing. 0.5.0 2006/05/19 Fix an assertion failure under _FFR_SELECT_SIGN_HEADERS. Reported by S. Moonesamy of Eland Systems. Under _FFR_REPORTINFO, only send reports when verification failed. There are other failure modes, but that's the only one for which reports are useful. Problem noted by Michael Thomas of Cisco. RFC2822 doesn't require any recipient headers, so remove those checks inside _FFR_REQUIRED_HEADERS. Fix bug #SF1481303: Don't verify DomainKeys signatures while in signing mode. Reported by S. Moonesamy of Eland Systems. Activate _FFR_MACRO_LIST (adds the "-M" command line option) and _FFR_EXTERNAL_IGNORE_LIST (adds the "-I" command line option). 0.4.1 2006/05/02 Include the list of supported DKIM versions in the output of "-V". Feature request #SF1238442: Add _FFR_VERIFY_DOMAINKEYS which will verify DomainKey signatures, if present. Requires libdk, which is available in the dk-milter package. Feature request #SF1453565: Add _FFR_SELECT_SIGN_HEADERS which permits specification of which headers to sign. Add _FFR_SET_DNS_CALLBACK which allows registration of a callback per-handle which is called periodically while waiting for DNS responses. LIBDKIM: Return an error if the signing function returned success but also reported a zero-length signature. Reported by S. Moonesamy of Eland Systems. 0.4.0 2006/04/18 Add preliminary support for IETF DKIM draft 01. "rsa-sha256" support was already added, but this also adds support for the "bh" (body hash) tag in signatures. Add "-v" command line switch to select DKIM version to use when signing. Add "-x" command line switch to specify a configuration file to read and parse. LIBAR: Fixes regarding retransmissions. 0.3.2 2006/04/05 Don't remove the wrong "b=" when canonicalizing the signature header during verification. Problem noted by Michael Thomas of Cisco. Properly process empty values in parameter sets. Problem noted by Michael Thomas of Cisco. 0.3.1 2006/03/19 Report the size of the key on successful verifications in the Authentication-Results: header. Fix bug #SF1453591: Tolerate empty strings in dkim_process_set(), and just apply defaults. LIBDKIM: Add dkim_getkeysize(), dkim_getsignalg(), dkim_getsigntime(). 0.3.0 2006/03/15 Add preliminary support for "rsa-sha256" signatures. Rearrange command line arguments somewhat. Include the list of supported canonicalization and signing algorithms in the output when "-V" is specified. Fix an intermittent crash condition caused by an uninitialized variable. Add _FFR_LOG_SSL_ERRORS to log any queued SSL error messages before releasing a message from the filter. 0.2.3 2006/03/03 Add a "testing" comment when the key or policy used to verify a message is marked with a test flag. Flush the base64 output stream before sending the reports under _FFR_REPORTINFO so that the reports don't contain truncated data. Discovered by Tony Hansen of AT&T. Fixes in processing of signature headers that contained extraneous spaces. Reported by Tony Hansen of AT&T. Fix bug #SF1442606: Clone the configuration string before parsing it so that "ps" doesn't show weird output. 0.2.2 2006/01/24 Evaluate the key granularity honouring "*" as a wildcard. Add _FFR_SET_REPLY which requests a more useful SMTP reply code when instructing the MTA to temp-fail or reject messages. 0.2.1 2005/12/09 Further fixes to dkim_getsighdr(). Problem reported by Sung-hoon Choi of Dreamwiz. Plug a few small but definite memory leaks. Fix bug #SF1373746: Repair a _FFR_SELECT_CANONICALIZATION build problem introduced in the previous release. Reported by S. Moonesamy of Eland Systems. 0.2.0 2005/12/02 Update for revised ESTG draft. Mainly this involved changing the "nowsp" canonicalization to "relaxed", and allowing specification of different canonicalizations for header and body. Don't allow the header to end with "\n\t" in dkim_getsighdr(). Problem reported by Sung-hoon Choi of Dreamwiz. Report "neutral" instead of "fail" for failed verifications when they key was marked as being in test mode. Patch from Sung-hoon Choi of Dreamwiz. Allow "-d" to specify a file from which domain names should be read, and allow domain names to contain wildcards. Fix bug #SF1243980: An empty key granularity matches nobody. Reported by Jim Fenton of Cisco. LIBAR: Fix bug #SF1282755: Fix a build issue introduced in the last release. Reported by Fredrik Pettai. 0.1.1 2005/07/21 Prevent a garbage pointer free() in dkim_free(). Reported by S. Moonesamy of Eland Systems. Fix bug #SF1241118: Don't add an Authentication-Results: header for messages which are unsigned and come from a domain that doesn't advertise a signs-all policy. Reported by S. Moonesamy of Eland Systems. Report "neutral" instead of "fail" for domains advertising test mode in their policies. Feature request #SF1238617: Add a compile-time option to map smfi_insheader() to smfi_addheader() on machines with older MTA and libmilter versions. 0.1.0 2005/07/13 Initial open source release. OpenDKIM-rel-opendkim-2-11-0-Beta2/announcement000066400000000000000000000016441337314105200210770ustar00rootroot00000000000000From: Murray S. Kucherawy To: opendkim-announce@lists.opendkim.org, opendkim-users@lists.opendkim.org Subject: OpenDKIM v2.10.3 released The Trusted Domain Project announces availability of OpenDKIM v2.10.3, now available for download from SourceForge. This release fixes a problem with strict header checking that was introduced in 2.10.0 which resulted in generation of faulty signatures. Upgrade is necessary only if you are using that feature. The full RELEASE_NOTES for this version: 2.10.3 2015/05/12 LIBOPENDKIM: Make strict header checking non-destructive. The last change to this code resulted in failing signatures. Reported by Pedro Morales and Wez Furlong. Please use the mailing lists at http://lists.opendkim.org/ to report problems. Bug reports and feature requests can be made through the project trackers, which can be found via http://www.opendkim.org. The Trusted Domain Project OpenDKIM-rel-opendkim-2-11-0-Beta2/autobuild/000077500000000000000000000000001337314105200204455ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/autobuild/.gitignore000066400000000000000000000001341337314105200224330ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno .deps/ .libs/ autom4te.cache/ core *.core autobuild OpenDKIM-rel-opendkim-2-11-0-Beta2/autobuild/Makefile.am000066400000000000000000000011241337314105200224770ustar00rootroot00000000000000# Copyright (c) 2010, 2012, 2014, The Trusted Domain Project. # All rights reserved. # what flags you want to pass to the C compiler & linker #AM_CFLAGS = --pedantic -Wall -O2 # this lists the binaries to produce, the (non-PHONY, binary) targets in # the previous manual Makefile if JANSSON bin_PROGRAMS = autobuild autobuild_SOURCES = autobuild.c autobuild_CPPFLAGS = $(LIBJANSSON_CPPFLAGS) autobuild_LDFLAGS = $(LIBJANSSON_LDFLAGS) autobuild_LDADD = $(LIBJANSSON_LIBS) -lm man_MANS = autobuild.8 dist_doc_DATA = autobuild.conf.sample endif EXTRA_DIST = autobuild.8 autobuild.conf.sample OpenDKIM-rel-opendkim-2-11-0-Beta2/autobuild/autobuild.8000066400000000000000000000046251337314105200225350ustar00rootroot00000000000000.TH autobuild 8 "The Trusted Domain Project" .SH NAME .B autobuild \- multiple configuration build tool .SH SYNOPSIS .B autobuild [\-c] [\-n] [\-t] [\-v] descr-file .SH DESCRIPTION .B autobuild configures, builds, and tests a source code package whose configuration is provided by GNU's .I autoconf mechanism. .I descr-file contains a set of parameters to be passed to .I configure in various combinations, followed by .I "make" and .I "make distcheck", to confirm that the current source code tree has not had any build or runtime regressions checked into it. If any of the three steps fails, the output of the command is dumped to standard output and execution terminates. .SH OPTIONS .TP .I \-c Print the configuration combinations, but do not execute them. .TP .I \-n Parse configuration file and exit without doing anything else. .TP .I \-t Print timestamps to stdout as each step is executed. .TP .I \-v Prints configuration combinations as their commands are executed. .SH DESCRIPTION FILE The description file contains a JSON object. It is expected to contain optional keys, which refer to arrays, as follows: .TP .I always Contains an array of strings each of which is an argument that should be passed to .I configure for every test configuration. .TP .I combine Contains an array of objects each of which is to be tested in various combinations with all of the others in the array. This means every entry added to this array doubles the number of test configurations that will be tried (i.e., the presence and absence cases). An object in this array must either be a string, or an array of strings; in the latter case, the set of strings is applied as a group whenever the array is selected for testing. .TP .I each Contains an array of objects each of which is to be tested in a mutually exclusive way (that is, in sequence, but never together). Exactly one will always be chosen and included. To cause an iteration that chooses none of the objects, include an empty object. .SH EXAMPLE { "always": [ "--foo", "--bar" ], "combine": [ "--a", "--b", [ "--c", "--d"]] } .PP This will run eight tests; all of them will include "--foo" and "--bar", and they will include all of the various possible combinationks of "--a", "--b", and the pair "--c" and "--d". .SH VERSION This man page covers version 1.1.0 of .I autobuild. .SH COPYRIGHT Copyright (c) 2012, 2013, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .B make(1) OpenDKIM-rel-opendkim-2-11-0-Beta2/autobuild/autobuild.c000066400000000000000000000340401337314105200226020ustar00rootroot00000000000000/* ** Copyright (c) 2012, 2013, The Trusted Domain Project. ** All rights reserved. */ #include #include #include #include #include #include #include #include #include #include #include #define JSON_ALWAYS "always" #define JSON_COMBINE "combine" #define JSON_EACH "each" #define AUTORECONF "autoreconf" #define CONFIGURE "./configure" #define MAKE "make" #define DISTCHECK "distcheck" #define CLEAN "clean" #define BUFRSZ 2048 #define TEMPLATE "/tmp/abXXXXXX" #ifndef MIN # define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif /* ! MIN */ #ifndef MAX # define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif /* ! MAX */ char *progname; /* ** DUMPARGS -- dump argument vector ** ** Parameters: ** where -- output stream ** args -- argument vector ** ** Return value: ** None. */ void dumpargs(FILE *where, const char **args) { int n; for (n = 0; args[n] != NULL; n++) fprintf(where, "%s%s\n", n == 0 ? "" : "\t", args[n]); } /* ** USAGE -- print usage message ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [options] descr-file\n" "\t-c\tshow combinations and exit\n" "\t-n\tparse descr-file and exit\n" "\t-t\tshow timestamps\n" "\t-v\tverbose mode\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int status; int m; int n; int fd; int showcombos = 0; int verbose = 0; int timestamps = 0; int confonly = 0; pid_t child; size_t combos; size_t asz; size_t c; size_t d; size_t bits; size_t nopts; size_t neach = 1; size_t nargs; size_t maxopts; size_t meach = 0; size_t xeach; json_t *j; json_t *node; json_t *always = NULL; json_t *combine = NULL; json_t *each = NULL; json_error_t err; void *iter; char *p; char *key; char *descr; const char **args; char buf[BUFRSZ]; char fn[MAXPATHLEN + 1]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, "cntv")) != -1) { switch (c) { case 'c': showcombos++; break; case 'n': confonly++; break; case 't': timestamps++; break; case 'v': verbose++; break; default: return usage(); } } if (optind >= argc) return usage(); descr = argv[optind]; j = json_load_file(descr, 0, &err); if (j == NULL) { fprintf(stderr, "%s: JSON input error from %s:\n" "\ttext = \"%s\"\n" "\tsource = \"%s\"\n" "\tline = %d\n" "\tcolumn = %d\n" "\toffset = %ld\n", progname, descr, err.text, err.source, err.line, err.column, err.position); return EX_DATAERR; } /* the top has to be an object */ if (!json_is_object(j)) { fprintf(stderr, "%s: %s: root object is not an object\n", progname, descr); json_decref(j); return EX_DATAERR; } /* ensure there are no top-level objects we don't expect */ for (iter = json_object_iter(j); iter != NULL; iter = json_object_iter_next(j, iter)) { key = (char *) json_object_iter_key(iter); node = json_object_iter_value(iter); if (strcasecmp(key, JSON_ALWAYS) != 0 && strcasecmp(key, JSON_EACH) != 0 && strcasecmp(key, JSON_COMBINE) != 0) { fprintf(stderr, "%s: %s: unexpected root object \"%s\"\n", progname, descr, key); json_decref(j); return EX_DATAERR; } else if (!json_is_array(node)) { fprintf(stderr, "%s: %s: root object \"%s\" is not an array\n", progname, descr, key); json_decref(j); return EX_DATAERR; } else if (strcasecmp(key, JSON_ALWAYS) == 0) { always = node; } else if (strcasecmp(key, JSON_EACH) == 0) { each = node; } else { combine = node; } } if (confonly > 0) { json_decref(j); return EX_OK; } nargs = 2; if (always != NULL) nargs += json_array_size(always); if (combine == NULL) nopts = 0; else nopts = json_array_size(combine); if (each == NULL) { neach = 1; } else { neach = json_array_size(each); for (n = 0; n < neach; n++) { node = json_array_get(each, n); if (json_is_array(node)) meach = MAX(json_array_size(node), meach); } } for (n = 0; n < nopts; n++) { node = json_array_get(combine, n); switch (json_typeof(node)) { case JSON_ARRAY: for (m = 0; m < json_array_size(node); m++) { if (!json_is_string(json_array_get(node, m))) { fprintf(stderr, "%s: %s: combine object at index %d is an array containing non-strings\n", progname, descr, n); return EX_DATAERR; } nargs++; } break; case JSON_STRING: nargs++; break; default: fprintf(stderr, "%s: %s: combine object at index %d is not a string or array\n", progname, descr, n); return EX_DATAERR; } } asz = sizeof(char *) * (nargs + nopts + meach + 2); args = (const char **) malloc(asz); if (args == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_OSERR; } combos = (size_t) pow(2, nopts) * neach; if (verbose > 1) { fprintf(stdout, "%s: max %d arguments, %d combinations\n", progname, nargs + nopts, combos); } /* autoreconf */ args[0] = AUTORECONF; args[1] = "-v"; args[2] = "-i"; args[3] = NULL; if (!showcombos) { strncpy(fn, TEMPLATE, sizeof fn); fd = mkstemp(fn); if (fd < 0) { fprintf(stderr, "%s: mkstemp(): %s\n", progname, strerror(errno)); return EX_OSERR; } (void) unlink(fn); child = fork(); switch (child) { case -1: fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); return EX_OSERR; case 0: (void) dup2(fd, 1); (void) dup2(fd, 2); (void) execvp(args[0], (char * const *) args); fprintf(stderr, "%s: execvp(): %s\n", progname, strerror(errno)); return EX_OSERR; default: n = wait(&status); if (n == -1) { fprintf(stderr, "%s: wait(): %s\n", progname, strerror(errno)); return EX_OSERR; } else if (WIFSIGNALED(status) || WEXITSTATUS(status) != 0) { if (WIFSIGNALED(status)) { fprintf(stderr, "%s: clean died with signal %d\n", progname, WTERMSIG(status)); } else { fprintf(stderr, "%s: clean exited with status %d\n", progname, WEXITSTATUS(status)); } (void) lseek(fd, 0, SEEK_SET); dumpargs(stdout, args); for (;;) { n = read(fd, buf, sizeof buf); (void) fwrite(buf, 1, n, stdout); if (n < sizeof buf) break; } close(fd); free(args); json_decref(j); return 1; } break; } /* clean up */ close(fd); } for (c = 0; c < combos; c++) { xeach = c % neach; memset(args, '\0', asz); bits = c; args[0] = CONFIGURE; n = 1; /* add the "always" arguments */ for (d = 0; d < json_array_size(always); d++) { node = json_array_get(always, d); args[n++] = json_string_value(node); } /* select the "each" argument */ if (each != NULL) { node = json_array_get(each, xeach); if (json_is_string(node)) { args[n++] = json_string_value(node); } else { json_t *sub; for (m = 0; m < json_array_size(node); m++) { sub = json_array_get(node, m); args[n++] = json_string_value(sub); } } } /* add the new combination of options */ for (d = 0; d < nopts; d++) { if ((c / neach) & (1 << d)) { node = json_array_get(combine, d); if (json_is_string(node)) { args[n++] = json_string_value(node); } else { json_t *sub; for (m = 0; m < json_array_size(node); m++) { sub = json_array_get(node, m); args[n++] = json_string_value(sub); } } } } if (showcombos) { dumpargs(stdout, args); continue; } if (verbose) { if (timestamps) { time_t now; (void) time(&now); fprintf(stdout, "%s: %s", progname, ctime(&now)); } fprintf(stdout, "%s: ", progname); dumpargs(stdout, args); } /* ./configure */ strncpy(fn, TEMPLATE, sizeof fn); fd = mkstemp(fn); if (fd < 0) { fprintf(stderr, "%s: mkstemp(): %s\n", progname, strerror(errno)); return EX_OSERR; } (void) unlink(fn); child = fork(); switch (child) { case -1: fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); return EX_OSERR; case 0: (void) dup2(fd, 1); (void) dup2(fd, 2); (void) execvp(args[0], (char * const *) args); fprintf(stderr, "%s: execvp(): %s\n", progname, strerror(errno)); return EX_OSERR; default: n = wait(&status); if (n == -1) { fprintf(stderr, "%s: wait(): %s\n", progname, strerror(errno)); return EX_OSERR; } else if (WIFSIGNALED(status) || WEXITSTATUS(status) != 0) { if (WIFSIGNALED(status)) { fprintf(stderr, "%s: configure died with signal %d\n", progname, WTERMSIG(status)); } else { fprintf(stderr, "%s: configure exited with status %d\n", progname, WEXITSTATUS(status)); } (void) lseek(fd, 0, SEEK_SET); dumpargs(stdout, args); for (;;) { n = read(fd, buf, sizeof buf); (void) fwrite(buf, 1, n, stdout); if (n < sizeof buf) break; } close(fd); free(args); json_decref(j); return 1; } break; } close(fd); /* make */ args[0] = MAKE; args[1] = NULL; strncpy(fn, TEMPLATE, sizeof fn); fd = mkstemp(fn); if (fd < 0) { fprintf(stderr, "%s: mkstemp(): %s\n", progname, strerror(errno)); return EX_OSERR; } (void) unlink(fn); child = fork(); switch (child) { case -1: fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); return EX_OSERR; case 0: (void) dup2(fd, 1); (void) dup2(fd, 2); (void) execvp(args[0], (char * const *) args); fprintf(stderr, "%s: execvp(): %s\n", progname, strerror(errno)); return EX_OSERR; default: n = wait(&status); if (n == -1) { fprintf(stderr, "%s: wait(): %s\n", progname, strerror(errno)); return EX_OSERR; } else if (WIFSIGNALED(status) || WEXITSTATUS(status) != 0) { if (WIFSIGNALED(status)) { fprintf(stderr, "%s: make died with signal %d\n", progname, WTERMSIG(status)); } else { fprintf(stderr, "%s: make exited with status %d\n", progname, WEXITSTATUS(status)); } (void) lseek(fd, 0, SEEK_SET); dumpargs(stdout, args); for (;;) { n = read(fd, buf, sizeof buf); (void) fwrite(buf, 1, n, stdout); if (n < sizeof buf) break; } close(fd); free(args); json_decref(j); return 1; } break; } close(fd); /* make distcheck */ args[0] = MAKE; args[1] = DISTCHECK; args[2] = NULL; strncpy(fn, TEMPLATE, sizeof fn); fd = mkstemp(fn); if (fd < 0) { fprintf(stderr, "%s: mkstemp(): %s\n", progname, strerror(errno)); return EX_OSERR; } (void) unlink(fn); child = fork(); switch (child) { case -1: fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); return EX_OSERR; case 0: (void) dup2(fd, 1); (void) dup2(fd, 2); (void) execvp(args[0], (char * const *) args); fprintf(stderr, "%s: execvp(): %s\n", progname, strerror(errno)); return EX_OSERR; default: n = wait(&status); if (n == -1) { fprintf(stderr, "%s: wait(): %s\n", progname, strerror(errno)); return EX_OSERR; } else if (WIFSIGNALED(status) || WEXITSTATUS(status) != 0) { if (WIFSIGNALED(status)) { fprintf(stderr, "%s: distcheck died with signal %d\n", progname, WTERMSIG(status)); } else { fprintf(stderr, "%s: distcheck exited with status %d\n", progname, WEXITSTATUS(status)); } (void) lseek(fd, 0, SEEK_SET); dumpargs(stdout, args); for (;;) { n = read(fd, buf, sizeof buf); (void) fwrite(buf, 1, n, stdout); if (n < sizeof buf) break; } close(fd); free(args); json_decref(j); return 1; } break; } /* clean up */ close(fd); /* make clean */ args[0] = MAKE; args[1] = CLEAN; args[2] = NULL; strncpy(fn, TEMPLATE, sizeof fn); fd = mkstemp(fn); if (fd < 0) { fprintf(stderr, "%s: mkstemp(): %s\n", progname, strerror(errno)); return EX_OSERR; } (void) unlink(fn); child = fork(); switch (child) { case -1: fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); return EX_OSERR; case 0: (void) dup2(fd, 1); (void) dup2(fd, 2); (void) execvp(args[0], (char * const *) args); fprintf(stderr, "%s: execvp(): %s\n", progname, strerror(errno)); return EX_OSERR; default: n = wait(&status); if (n == -1) { fprintf(stderr, "%s: wait(): %s\n", progname, strerror(errno)); return EX_OSERR; } else if (WIFSIGNALED(status) || WEXITSTATUS(status) != 0) { if (WIFSIGNALED(status)) { fprintf(stderr, "%s: clean died with signal %d\n", progname, WTERMSIG(status)); } else { fprintf(stderr, "%s: clean exited with status %d\n", progname, WEXITSTATUS(status)); } (void) lseek(fd, 0, SEEK_SET); dumpargs(stdout, args); for (;;) { n = read(fd, buf, sizeof buf); (void) fwrite(buf, 1, n, stdout); if (n < sizeof buf) break; } close(fd); free(args); json_decref(j); return 1; } break; } /* clean up */ close(fd); } return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/autobuild/autobuild.conf.sample000066400000000000000000000007711337314105200245710ustar00rootroot00000000000000{ "always": [ "--with-openssl=/usr/local", "--with-milter=/usr/local" ], "combine": [ "--enable-debug", "--disable-shared", "--with-odbx", [ "--enable-rbl", "--enable-stats", "--enable-statsext", "--with-lua" ], "--enable-diffheaders", "--enable-vbr", "--enable-atps", "--with-unbound", "--enable-replace_rules", "--with-libmemcached", "--enable-rate_limit", "--enable-reputation", "--enable-dkim_reputation", "--with-openldap", "--enable-resign" ] } OpenDKIM-rel-opendkim-2-11-0-Beta2/build-aux/000077500000000000000000000000001337314105200203475ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/build-aux/.gitignore000066400000000000000000000000111337314105200223270ustar00rootroot00000000000000[cdilm]* OpenDKIM-rel-opendkim-2-11-0-Beta2/build-aux/README000066400000000000000000000001401337314105200212220ustar00rootroot00000000000000 This directory is a placeholder for scripts generated during or required by the build process. OpenDKIM-rel-opendkim-2-11-0-Beta2/buildtest000066400000000000000000000031551337314105200204030ustar00rootroot00000000000000#!/bin/sh # # buildtest -- build and test with numerous option combinations # # configuration module="opendkim" version="$1" buildtop="`echo $1 | sed 's/-[A-Za-z0-9]*//g'`" download="http://downloads.sourceforge.net/project/${module}/${module}-${version}.tar.gz" buildroot=/var/tmp # setup buildtime="`date +%Y%m%d%H%M%S`" buildname="${module}-${buildtime}" builddir="${buildroot}/${buildname}" # create directories mkdir $builddir cd $builddir # download and unpack wget -q $download gunzip -c `basename $download` | tar xf - cd ${module}-${buildtop} for i in --enable-filter \ --with-db \ --with-odbx \ --with-tre \ --with-unbound \ --enable-allsymbols \ --enable-bodylengthdb \ --enable-capture_unknown_errors \ --enable-diffheaders \ --enable-dkim_reputation \ --enable-dnsupgrade \ --enable-identity_header \ --enable-parsetime \ --enable-redirect \ --enable-replace_rules \ --enable-report_intervals \ --enable-resign \ --enable-select_canonicalization \ --enable-selector_header \ --enable-sender_macro \ --enable-stats \ --enable-vbr \ --enable-ztags do # configure ./configure $CONFIG_OPTS $i > configure.out 2>&1 if test $? != 0 then echo "${buildname} ./configure error" tail -20 configure.out exit 1 fi # make make > make.out 2>&1 if test $? != 0 then echo "${buildname} make error" tail -20 make.out exit 1 fi # make check make check > make.out 2>&1 if test $? != 0 then echo "${buildname} make check error" tail -20 make.out exit 1 fi # make clean rm make.out configure.out make clean > /dev/null 2>&1 done cd $HOME rm -rf $builddir exit 0 OpenDKIM-rel-opendkim-2-11-0-Beta2/configure000077500000000000000000024376311337314105200204040ustar00rootroot00000000000000#! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for OpenDKIM 2.11.0. # # Report bugs to . # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # Use a proper internal environment variable to ensure we don't fall # into an infinite loop, continuously re-executing ourselves. if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then _as_can_reexec=no; export _as_can_reexec; # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 as_fn_exit 255 fi # We don't want this to propagate to other subprocesses. { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 " as_required="as_fn_return () { (exit \$1); } as_fn_success () { as_fn_return 0; } as_fn_failure () { as_fn_return 1; } as_fn_ret_success () { return 0; } as_fn_ret_failure () { return 1; } exitcode=0 as_fn_success || { exitcode=1; echo as_fn_success failed.; } as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi test x\$exitcode = x0 || exit 1 test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO PATH=/empty FPATH=/empty; export PATH FPATH test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else as_have_required=no fi if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_found=false for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. as_found=: case $as_dir in #( /*) for as_base in sh bash ksh sh5; do # Try only shells that exist, to save several forks. as_shell=$as_dir/$as_base if { test -f "$as_shell" || test -f "$as_shell.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : CONFIG_SHELL=$as_shell as_have_required=yes if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : break 2 fi fi done;; esac as_found=false done $as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : CONFIG_SHELL=$SHELL as_have_required=yes fi; } IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : export CONFIG_SHELL # We cannot yet assume a decent shell, so we have to provide a # neutralization value for shells without unset; and this also # works around shells that cannot unset nonexistent variables. # Preserve -v and -x to the replacement shell. BASH_ENV=/dev/null ENV=/dev/null (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV case $- in # (((( *v*x* | *x*v* ) as_opts=-vx ;; *v* ) as_opts=-v ;; *x* ) as_opts=-x ;; * ) as_opts= ;; esac exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} # Admittedly, this is quite paranoid, since all the known shells bail # out after a failed `exec'. $as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 exit 255 fi if test x$as_have_required = xno; then : $as_echo "$0: This script requires a shell more modern than all" $as_echo "$0: the shells that I found on your system." if test x${ZSH_VERSION+set} = xset ; then $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" $as_echo "$0: be upgraded to zsh 4.3.4 or later." else $as_echo "$0: Please tell bug-autoconf@gnu.org and bugs@opendkim.org $0: about your system, including any error possibly output $0: before this message. Then install a modern shell, or $0: manually run the script under such a shell if you do $0: have one." fi exit 1 fi fi fi SHELL=${CONFIG_SHELL-/bin/sh} export SHELL # Unset more variables known to interfere with behavior of common tools. CLICOLOR_FORCE= GREP_OPTIONS= unset CLICOLOR_FORCE GREP_OPTIONS ## --------------------- ## ## M4sh Shell Functions. ## ## --------------------- ## # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits as_lineno_1=$LINENO as_lineno_1a=$LINENO as_lineno_2=$LINENO as_lineno_2a=$LINENO eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) sed -n ' p /[$]LINENO/= ' <$as_myself | sed ' s/[$]LINENO.*/&-/ t lineno b :lineno N :loop s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ t loop s/-\n.*// ' >$as_me.lineno && chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } # If we had to re-execute with $CONFIG_SHELL, we're ensured to have # already done that, so ensure we don't try to do so again and fall # in an infinite loop. This has already happened in practice. _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). . "./$as_me.lineno" # Exit status is that of the last command. exit } ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" SHELL=${CONFIG_SHELL-/bin/sh} test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. # hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` # # Initializations. # ac_default_prefix=/usr/local ac_clean_files= ac_config_libobj_dir=. LIBOBJS= cross_compiling=no subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='OpenDKIM' PACKAGE_TARNAME='opendkim' PACKAGE_VERSION='2.11.0' PACKAGE_STRING='OpenDKIM 2.11.0' PACKAGE_BUGREPORT='bugs@opendkim.org' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef STDC_HEADERS # include # include #else # ifdef HAVE_STDLIB_H # include # endif #endif #ifdef HAVE_STRING_H # if !defined STDC_HEADERS && defined HAVE_MEMORY_H # include # endif # include #endif #ifdef HAVE_STRINGS_H # include #endif #ifdef HAVE_INTTYPES_H # include #endif #ifdef HAVE_STDINT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif" ac_header_list= ac_func_list= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS SPECBUILDREQUIRES SPECREQUIRES SPECCONFIGURE SPECBINDIR SYSCONFDIR LIBERL_LIBS LIBERL_LIBDIRS LIBERL_INCDIRS ERLANG_FALSE ERLANG_TRUE LIBERL_MANNOTICE DOMAIN domainname TESTSOCKET TEST_SOCKET_FALSE TEST_SOCKET_TRUE LIVE_TESTS_FALSE LIVE_TESTS_TRUE LIBOPENDKIM_INC LIBOPENDKIM_LIBS_PKG LIBOPENDKIM_LIBS LIBDB_LIBS LIBDB_LIBDIRS LIBDB_INCDIRS USE_DB_LIBOPENDKIM_FALSE USE_DB_LIBOPENDKIM_TRUE USE_DB_OPENDKIM_FALSE USE_DB_OPENDKIM_TRUE JANSSON_FALSE JANSSON_TRUE LIBJANSSON_LDFLAGS LIBJANSSON_CPPFLAGS LIBJANSSON_LIBS LIBJANSSON_CFLAGS CURL_LDFLAGS CURL_CPPFLAGS LIBCURL_MANNOTICE CURL_LIBS CURL_CFLAGS LIBMDB_LIBS LIBMDB_CPPFLAGS USE_MDB_FALSE USE_MDB_TRUE SASL_CPPFLAGS USE_SASL_FALSE USE_SASL_TRUE SASL_LIBS SASL_CFLAGS OPENLDAP_CPPFLAGS USE_LDAP_FALSE USE_LDAP_TRUE OPENLDAP_LIBS OPENLDAP_CFLAGS LIBODBX_LDFLAGS LIBODBX_CPPFLAGS USE_ODBX_FALSE USE_ODBX_TRUE LIBODBX_LIBS LIBODBX_CFLAGS SQL_BACKEND LIBLUA_LIBDIRS LIBLUA_INCDIRS LUA_FALSE LUA_TRUE LUA_MANNOTICE LIBLUA_LIBS LIBLUA_CFLAGS LIBTRE_CPPFLAGS USE_TRE_FALSE USE_TRE_TRUE LIBTRE_LIBS LIBTRE_CFLAGS LIBEVENT_LIBS LIBEVENT_LIBDIRS LIBLDNS_LIBS LIBLDNS_LIBDIRS LIBUNBOUND_LIBS LIBUNBOUND_LIBDIRS LIBUNBOUND_INCDIRS USE_UNBOUND_FALSE USE_UNBOUND_TRUE UNBOUND_MANNOTICE LIBMEMCACHED_LIBDIRS LIBMEMCACHED_INCDIRS USE_LIBMEMCACHED_FALSE USE_LIBMEMCACHED_TRUE LIBMEMCACHED_MANNOTICE LIBMEMCACHED_LIBS LIBMEMCACHED_CFLAGS USE_RRD_FALSE USE_RRD_TRUE LIBRRD_MANNOTICE RRDTOOL_LIBS RRDTOOL_CFLAGS LIBMILTER_LIBS LIBMILTER_LIBDIRS LIBMILTER_INCDIRS LIBCRYPTO_LIBDIRS LIBCRYPTO_CPPFLAGS LIBCRYPTO_LIBS LIBCRYPTO_CFLAGS USE_GNUTLS_FALSE USE_GNUTLS_TRUE GNUTLS_LIBS GNUTLS_CFLAGS DEBUG_FALSE DEBUG_TRUE ALL_SYMBOLS_FALSE ALL_SYMBOLS_TRUE QUERY_CACHE_MANNOTICE BUILD_FILTER_FALSE BUILD_FILTER_TRUE GPROF_FILENAMES_FALSE GPROF_FILENAMES_TRUE GPROF_FALSE GPROF_TRUE GCOV_ONLY_FALSE GCOV_ONLY_TRUE GCOV_FALSE GCOV_TRUE LCOV_FALSE LCOV_TRUE COV_LIBADD COV_LDFLAGS COV_CFLAGS haslcov hasgcov hasgprof hascc hasgcc RPATH_FALSE RPATH_TRUE SENDMAIL_PATH DEFAULT_SENDER_MANNOTICE VBR_FALSE VBR_TRUE VBR_MANNOTICE RBL_FALSE RBL_TRUE RBL_MANNOTICE STATSEXT_MANNOTICE STATS_FALSE STATS_TRUE STATS_MANNOTICE SOCKETDB_MANNOTICE SENDER_MACRO_MANNOTICE RESIGN_MANNOTICE REPUTE_FALSE REPUTE_TRUE REPUTATION_MANNOTICE hasrrdtool REPRRD_FALSE REPRRD_TRUE REPRRD_MANNOTICE REPLACE_RULES_FALSE REPLACE_RULES_TRUE REPLACE_RULES_MANNOTICE RATE_LIMIT_MANNOTICE POSTGRESQL_RECONNECT_HACK_MANNOTICE LDAP_CACHING_MANNOTICE IDENTITY_HEADER_MANNOTICE DIFFHEADERS_MANNOTICE DB_HANDLE_POOLS_MANNOTICE CONDITIONAL_FALSE CONDITIONAL_TRUE CONDITIONAL_MANNOTICE ATPS_FALSE ATPS_TRUE ATPS_MANNOTICE POLL_MANNOTICE POPAUTH_MANNOTICE LIBOBJS LIBRESOLV LIBDL_LIBS LIBNSL_LIBS PTHREAD_CFLAGS PTHREAD_LIBS PTHREAD_CC ax_pthread_config PKG_CONFIG_LIBDIR PKG_CONFIG_PATH PKG_CONFIG CPP OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL MANIFEST_TOOL RANLIB ac_ct_AR AR DLLTOOL OBJDUMP LN_S NM ac_ct_DUMPBIN DUMPBIN LD FGREP EGREP GREP SED host_os host_vendor host_cpu host build_os build_vendor build_cpu build LIBTOOL am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE am__quote am__include DEPDIR OBJEXT EXEEXT ac_ct_CC CPPFLAGS LDFLAGS CFLAGS CC LIBOPENDKIM_VERSION_INFO HEX_VERSION AM_BACKSLASH AM_DEFAULT_VERBOSITY AM_DEFAULT_V AM_V am__untar am__tar AMTAR am__leading_dot SET_MAKE AWK mkdir_p MKDIR_P INSTALL_STRIP_PROGRAM STRIP install_sh MAKEINFO AUTOHEADER AUTOMAKE AUTOCONF ACLOCAL VERSION PACKAGE CYGPATH_W am__isrc INSTALL_DATA INSTALL_SCRIPT INSTALL_PROGRAM target_alias host_alias build_alias LIBS ECHO_T ECHO_N ECHO_C DEFS mandir localedir libdir psdir pdfdir dvidir htmldir infodir docdir oldincludedir includedir localstatedir sharedstatedir sysconfdir datadir datarootdir libexecdir sbindir bindir program_transform_name prefix exec_prefix PACKAGE_URL PACKAGE_BUGREPORT PACKAGE_STRING PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR SHELL' ac_subst_files='' ac_user_opts=' enable_option_checking enable_silent_rules enable_dependency_tracking enable_shared enable_static with_pic enable_fast_install with_gnu_ld with_sysroot enable_libtool_lock enable_popauth enable_poll enable_atps enable_conditional enable_db_handle_pools enable_diffheaders enable_identity_header enable_ldap_caching enable_postgresql_reconnect_hack enable_rate_limit enable_replace_rules enable_reprrd enable_reputation enable_resign enable_sender_macro enable_socketdb enable_stats enable_statsext enable_rbl enable_vbr enable_default_sender enable_rpath enable_codecoverage with_gprof with_gcov with_lcov enable_filter enable_query_cache enable_allsymbols enable_debug with_gnutls with_openssl with_milter with_librrd with_libmemcached with_unbound with_ldns with_libevent with_tre with_lua with_sql_backend with_odbx with_openldap with_sasl with_lmdb with_libcurl with_libjansson with_db_incdir with_db_libdir with_db_lib with_db enable_live_testing with_test_socket with_domain with_erlang ' ac_precious_vars='build_alias host_alias target_alias CC CFLAGS LDFLAGS LIBS CPPFLAGS CPP PKG_CONFIG PKG_CONFIG_PATH PKG_CONFIG_LIBDIR GNUTLS_CFLAGS GNUTLS_LIBS LIBCRYPTO_CFLAGS LIBCRYPTO_LIBS RRDTOOL_CFLAGS RRDTOOL_LIBS LIBMEMCACHED_CFLAGS LIBMEMCACHED_LIBS LIBTRE_CFLAGS LIBTRE_LIBS LIBLUA_CFLAGS LIBLUA_LIBS LIBODBX_CFLAGS LIBODBX_LIBS OPENLDAP_CFLAGS OPENLDAP_LIBS SASL_CFLAGS SASL_LIBS CURL_CFLAGS CURL_LIBS LIBJANSSON_CFLAGS LIBJANSSON_LIBS' # Initialize some variables set by options. ac_init_help= ac_init_version=false ac_unrecognized_opts= ac_unrecognized_sep= # The variables have the same names as the options, with # dashes changed to underlines. cache_file=/dev/null exec_prefix=NONE no_create= no_recursion= prefix=NONE program_prefix=NONE program_suffix=NONE program_transform_name=s,x,x, silent= site= srcdir= verbose= x_includes=NONE x_libraries=NONE # Installation directory options. # These are left unexpanded so users can "make install exec_prefix=/foo" # and all the variables that are supposed to be based on exec_prefix # by default will actually change. # Use braces instead of parens because sh, perl, etc. also accept them. # (The list follows the same order as the GNU Coding Standards.) bindir='${exec_prefix}/bin' sbindir='${exec_prefix}/sbin' libexecdir='${exec_prefix}/libexec' datarootdir='${prefix}/share' datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' infodir='${datarootdir}/info' htmldir='${docdir}' dvidir='${docdir}' pdfdir='${docdir}' psdir='${docdir}' libdir='${exec_prefix}/lib' localedir='${datarootdir}/locale' mandir='${datarootdir}/man' ac_prev= ac_dashdash= for ac_option do # If the previous option needs an argument, assign it. if test -n "$ac_prev"; then eval $ac_prev=\$ac_option ac_prev= continue fi case $ac_option in *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; *=) ac_optarg= ;; *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. case $ac_dashdash$ac_option in --) ac_dashdash=yes ;; -bindir | --bindir | --bindi | --bind | --bin | --bi) ac_prev=bindir ;; -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) bindir=$ac_optarg ;; -build | --build | --buil | --bui | --bu) ac_prev=build_alias ;; -build=* | --build=* | --buil=* | --bui=* | --bu=*) build_alias=$ac_optarg ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) ac_prev=cache_file ;; -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file=$ac_optarg ;; --config-cache | -C) cache_file=config.cache ;; -datadir | --datadir | --datadi | --datad) ac_prev=datadir ;; -datadir=* | --datadir=* | --datadi=* | --datad=*) datadir=$ac_optarg ;; -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ | --dataroo | --dataro | --datar) ac_prev=datarootdir ;; -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) datarootdir=$ac_optarg ;; -disable-* | --disable-*) ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=no ;; -docdir | --docdir | --docdi | --doc | --do) ac_prev=docdir ;; -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) docdir=$ac_optarg ;; -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) ac_prev=dvidir ;; -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) dvidir=$ac_optarg ;; -enable-* | --enable-*) ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "enable_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval enable_$ac_useropt=\$ac_optarg ;; -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ | --exec | --exe | --ex) ac_prev=exec_prefix ;; -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ | --exec=* | --exe=* | --ex=*) exec_prefix=$ac_optarg ;; -gas | --gas | --ga | --g) # Obsolete; use --with-gas. with_gas=yes ;; -help | --help | --hel | --he | -h) ac_init_help=long ;; -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) ac_init_help=recursive ;; -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) ac_init_help=short ;; -host | --host | --hos | --ho) ac_prev=host_alias ;; -host=* | --host=* | --hos=* | --ho=*) host_alias=$ac_optarg ;; -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) ac_prev=htmldir ;; -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ | --ht=*) htmldir=$ac_optarg ;; -includedir | --includedir | --includedi | --included | --include \ | --includ | --inclu | --incl | --inc) ac_prev=includedir ;; -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ | --includ=* | --inclu=* | --incl=* | --inc=*) includedir=$ac_optarg ;; -infodir | --infodir | --infodi | --infod | --info | --inf) ac_prev=infodir ;; -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) infodir=$ac_optarg ;; -libdir | --libdir | --libdi | --libd) ac_prev=libdir ;; -libdir=* | --libdir=* | --libdi=* | --libd=*) libdir=$ac_optarg ;; -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ | --libexe | --libex | --libe) ac_prev=libexecdir ;; -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ | --libexe=* | --libex=* | --libe=*) libexecdir=$ac_optarg ;; -localedir | --localedir | --localedi | --localed | --locale) ac_prev=localedir ;; -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) localedir=$ac_optarg ;; -localstatedir | --localstatedir | --localstatedi | --localstated \ | --localstate | --localstat | --localsta | --localst | --locals) ac_prev=localstatedir ;; -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) localstatedir=$ac_optarg ;; -mandir | --mandir | --mandi | --mand | --man | --ma | --m) ac_prev=mandir ;; -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) mandir=$ac_optarg ;; -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; -no-create | --no-create | --no-creat | --no-crea | --no-cre \ | --no-cr | --no-c | -n) no_create=yes ;; -no-recursion | --no-recursion | --no-recursio | --no-recursi \ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ | --oldin | --oldi | --old | --ol | --o) ac_prev=oldincludedir ;; -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) oldincludedir=$ac_optarg ;; -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) prefix=$ac_optarg ;; -program-prefix | --program-prefix | --program-prefi | --program-pref \ | --program-pre | --program-pr | --program-p) ac_prev=program_prefix ;; -program-prefix=* | --program-prefix=* | --program-prefi=* \ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) program_prefix=$ac_optarg ;; -program-suffix | --program-suffix | --program-suffi | --program-suff \ | --program-suf | --program-su | --program-s) ac_prev=program_suffix ;; -program-suffix=* | --program-suffix=* | --program-suffi=* \ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) program_suffix=$ac_optarg ;; -program-transform-name | --program-transform-name \ | --program-transform-nam | --program-transform-na \ | --program-transform-n | --program-transform- \ | --program-transform | --program-transfor \ | --program-transfo | --program-transf \ | --program-trans | --program-tran \ | --progr-tra | --program-tr | --program-t) ac_prev=program_transform_name ;; -program-transform-name=* | --program-transform-name=* \ | --program-transform-nam=* | --program-transform-na=* \ | --program-transform-n=* | --program-transform-=* \ | --program-transform=* | --program-transfor=* \ | --program-transfo=* | --program-transf=* \ | --program-trans=* | --program-tran=* \ | --progr-tra=* | --program-tr=* | --program-t=*) program_transform_name=$ac_optarg ;; -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) ac_prev=pdfdir ;; -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) pdfdir=$ac_optarg ;; -psdir | --psdir | --psdi | --psd | --ps) ac_prev=psdir ;; -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) psdir=$ac_optarg ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ | --sbi=* | --sb=*) sbindir=$ac_optarg ;; -sharedstatedir | --sharedstatedir | --sharedstatedi \ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ | --sharedst | --shareds | --shared | --share | --shar \ | --sha | --sh) ac_prev=sharedstatedir ;; -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ | --sha=* | --sh=*) sharedstatedir=$ac_optarg ;; -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) site=$ac_optarg ;; -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) ac_prev=srcdir ;; -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir=$ac_optarg ;; -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ | --syscon | --sysco | --sysc | --sys | --sy) ac_prev=sysconfdir ;; -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) sysconfdir=$ac_optarg ;; -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target_alias ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) target_alias=$ac_optarg ;; -v | -verbose | --verbose | --verbos | --verbo | --verb) verbose=yes ;; -version | --version | --versio | --versi | --vers | -V) ac_init_version=: ;; -with-* | --with-*) ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=\$ac_optarg ;; -without-* | --without-*) ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in *" "with_$ac_useropt" "*) ;; *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" ac_unrecognized_sep=', ';; esac eval with_$ac_useropt=no ;; --x) # Obsolete; use --with-x. with_x=yes ;; -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ | --x-incl | --x-inc | --x-in | --x-i) ac_prev=x_includes ;; -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) x_includes=$ac_optarg ;; -x-libraries | --x-libraries | --x-librarie | --x-librari \ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) ac_prev=x_libraries ;; -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; -*) as_fn_error $? "unrecognized option: \`$ac_option' Try \`$0 --help' for more information" ;; *=*) ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; *) # FIXME: should be removed in autoconf 3.0. $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi # Check all directory arguments for consistency. for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. case $ac_val in */ ) ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` eval $ac_var=\$ac_val;; esac # Be sure to have absolute directory names. case $ac_val in [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' # used to hold the argument of --host etc. # FIXME: To remove some day. build=$build_alias host=$host_alias target=$target_alias # FIXME: To remove some day. if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi fi ac_tool_prefix= test -n "$host_alias" && ac_tool_prefix=$host_alias- test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. if test -z "$srcdir"; then ac_srcdir_defaulted=yes # Try the directory containing this script, then the parent directory. ac_confdir=`$as_dirname -- "$as_myself" || $as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_myself" : 'X\(//\)[^/]' \| \ X"$as_myself" : 'X\(//\)$' \| \ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_myself" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` srcdir=$ac_confdir if test ! -r "$srcdir/$ac_unique_file"; then srcdir=.. fi else ac_srcdir_defaulted=no fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then srcdir=. fi # Remove unnecessary trailing slashes from srcdir. # Double slashes in file names in object file debugging info # mess up M-x gdb in Emacs. case $srcdir in */) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; esac for ac_var in $ac_precious_vars; do eval ac_env_${ac_var}_set=\${${ac_var}+set} eval ac_env_${ac_var}_value=\$${ac_var} eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} eval ac_cv_env_${ac_var}_value=\$${ac_var} done # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures OpenDKIM 2.11.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Configuration: -h, --help display this help and exit --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files --srcdir=DIR find the sources in DIR [configure dir or \`..'] Installation directories: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [PREFIX] By default, \`make install' will install all the files in \`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify an installation prefix other than \`$ac_default_prefix' using \`--prefix', for instance \`--prefix=\$HOME'. For better control, use the options below. Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --sbindir=DIR system admin executables [EPREFIX/sbin] --libexecdir=DIR program executables [EPREFIX/libexec] --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] --datadir=DIR read-only architecture-independent data [DATAROOTDIR] --infodir=DIR info documentation [DATAROOTDIR/info] --localedir=DIR locale-dependent data [DATAROOTDIR/locale] --mandir=DIR man documentation [DATAROOTDIR/man] --docdir=DIR documentation root [DATAROOTDIR/doc/opendkim] --htmldir=DIR html documentation [DOCDIR] --dvidir=DIR dvi documentation [DOCDIR] --pdfdir=DIR pdf documentation [DOCDIR] --psdir=DIR ps documentation [DOCDIR] _ACEOF cat <<\_ACEOF Program names: --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names --program-transform-name=PROGRAM run sed PROGRAM on installed program names System types: --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of OpenDKIM 2.11.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --enable-silent-rules less verbose build output (undo: "make V=1") --disable-silent-rules verbose build output (undo: "make V=0") --enable-dependency-tracking do not reject slow dependency extractors --disable-dependency-tracking speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) --enable-popauth enable POP-before-SMTP support --enable-poll use poll() instead of select() --enable-atps experimental Authorized Third Party Signers checks --enable-conditional experimental conditional signatures --enable-db_handle_pools experimental database handle pools --enable-diffheaders compare signed and verified headers when possible --enable-identity_header special header to set identity --enable-ldap_caching LDAP query piggybacking and caching --enable-postgresql_reconnect_hack hack to overcome PostgreSQL connection error detection bug --enable-rate_limit support for DKIM-based rate limiting --enable-replace_rules support for string substitution when signing --enable-reprrd support for experimental reputation checks using RRD --enable-reputation support for experimental reputation checks --enable-resign support for one-step re-signing --enable-sender_macro macro to determine sender --enable-socketdb arbitrary socket data sets --enable-stats stats recording and reporting --enable-statsext extended stats recording and reporting --enable-rbl Realtime Blacklist query support --enable-vbr Vouch-By-Reference support --enable-default_sender default sender address --enable-rpath include library load paths in binaries --enable-codecoverage include code coverage/profiling code --disable-filter do not compile the opendkim filter --enable-query_cache local key caching --enable-allsymbols export internal-use symbols for better test coverage --enable-debug produce debugging binaries and libraries --disable-live-testing disable tests that require Internet access Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-sysroot=DIR Search for dependent libraries within DIR (or the compiler's sysroot if not specified). --with-gprof profiling with gprof --with-gcov profiling with gcov --with-lcov profiling with lcov --with-gnutls location of GnuTLS includes and library --with-openssl location of OpenSSL includes and library --with-milter location of milter includes and library --with-librrd location of librrd includes and library --with-libmemcached location of libmemcached includes and library --with-unbound location of Unbound includes and library --with-ldns location of ldns includes and library --with-libevent location of libevent includes and library --with-tre location of TRE includes and library --with-lua location of Lua includes and library --with-sql-backend selection of SQL backend in use --with-odbx location of OpenDBX includes and library --with-openldap location of OpenLDAP includes and library --with-sasl location of SASL includes --with-lmdb location of OpenLDAP MDB includes and library --with-libcurl location of CURL includes and library --with-libjansson location of jansson includes and library --with-db-incdir location of BerkeleyDB includes --with-db-libdir location of BerkeleyDB library --with-db-lib name of BerkeleyDB library --with-db location of BerkeleyDB includes and library --with-test-socket specify socket to use for all tests --with-domain name of the domain for signing - sets this in sample configuration files --with-erlang location of Erlang includes and library Some influential environment variables: CC C compiler command CFLAGS C compiler flags LDFLAGS linker flags, e.g. -L if you have libraries in a nonstandard directory LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory CPP C preprocessor PKG_CONFIG path to pkg-config utility PKG_CONFIG_PATH directories to add to pkg-config's search path PKG_CONFIG_LIBDIR path overriding pkg-config's built-in search path GNUTLS_CFLAGS C compiler flags for GNUTLS, overriding pkg-config GNUTLS_LIBS linker flags for GNUTLS, overriding pkg-config LIBCRYPTO_CFLAGS C compiler flags for LIBCRYPTO, overriding pkg-config LIBCRYPTO_LIBS linker flags for LIBCRYPTO, overriding pkg-config RRDTOOL_CFLAGS C compiler flags for RRDTOOL, overriding pkg-config RRDTOOL_LIBS linker flags for RRDTOOL, overriding pkg-config LIBMEMCACHED_CFLAGS C compiler flags for LIBMEMCACHED, overriding pkg-config LIBMEMCACHED_LIBS linker flags for LIBMEMCACHED, overriding pkg-config LIBTRE_CFLAGS C compiler flags for LIBTRE, overriding pkg-config LIBTRE_LIBS linker flags for LIBTRE, overriding pkg-config LIBLUA_CFLAGS C compiler flags for LIBLUA, overriding pkg-config LIBLUA_LIBS linker flags for LIBLUA, overriding pkg-config LIBODBX_CFLAGS C compiler flags for LIBODBX, overriding pkg-config LIBODBX_LIBS linker flags for LIBODBX, overriding pkg-config OPENLDAP_CFLAGS C compiler flags for OPENLDAP, overriding pkg-config OPENLDAP_LIBS linker flags for OPENLDAP, overriding pkg-config SASL_CFLAGS C compiler flags for SASL, overriding pkg-config SASL_LIBS linker flags for SASL, overriding pkg-config CURL_CFLAGS C compiler flags for CURL, overriding pkg-config CURL_LIBS linker flags for CURL, overriding pkg-config LIBJANSSON_CFLAGS C compiler flags for LIBJANSSON, overriding pkg-config LIBJANSSON_LIBS linker flags for LIBJANSSON, overriding pkg-config Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. Report bugs to . _ACEOF ac_status=$? fi if test "$ac_init_help" = "recursive"; then # If there are subdirs, report their specific --help. for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue test -d "$ac_dir" || { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || continue ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix cd "$ac_dir" || { ac_status=$?; continue; } # Check for guested configure. if test -f "$ac_srcdir/configure.gnu"; then echo && $SHELL "$ac_srcdir/configure.gnu" --help=recursive elif test -f "$ac_srcdir/configure"; then echo && $SHELL "$ac_srcdir/configure" --help=recursive else $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 fi || ac_status=$? cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF OpenDKIM configure 2.11.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi ## ------------------------ ## ## Autoconf initialization. ## ## ------------------------ ## # ac_fn_c_try_compile LINENO # -------------------------- # Try to compile conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest.$ac_objext; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile # ac_fn_c_try_link LINENO # ----------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_link () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack rm -f conftest.$ac_objext conftest$ac_exeext if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { test -z "$ac_c_werror_flag" || test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || test -x conftest$ac_exeext }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link # ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists and can be compiled using the include files in # INCLUDES, setting the cache variable VAR accordingly. ac_fn_c_check_header_compile () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile # ac_fn_c_try_cpp LINENO # ---------------------- # Try to preprocess conftest.$ac_ext, and return whether this succeeded. ac_fn_c_try_cpp () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_cpp conftest.$ac_ext" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err ac_status=$? if test -s conftest.err; then grep -v '^ *+' conftest.err >conftest.er1 cat conftest.er1 >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : ac_retval=0 else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp # ac_fn_c_try_run LINENO # ---------------------- # Try to link conftest.$ac_ext, and return whether this succeeded. Assumes # that executables *can* be run. ac_fn_c_try_run () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then : ac_retval=0 else $as_echo "$as_me: program exited with status $ac_status" >&5 $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run # ac_fn_c_check_func LINENO FUNC VAR # ---------------------------------- # Tests whether FUNC exists, setting the cache variable VAR accordingly ac_fn_c_check_func () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Define $2 to an innocuous variant, in case declares $2. For example, HP-UX 11i declares gettimeofday. */ #define $2 innocuous_$2 /* System header to define __stub macros and hopefully few prototypes, which can conflict with char $2 (); below. Prefer to if __STDC__ is defined, since exists even on freestanding compilers. */ #ifdef __STDC__ # include #else # include #endif #undef $2 /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char $2 (); /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ #if defined __stub_$2 || defined __stub___$2 choke me #endif int main () { return $2 (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache # variable VAR accordingly. ac_fn_c_check_type () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof ($2)) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { if (sizeof (($2))) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else eval "$3=yes" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using # the include files in INCLUDES and setting the cache variable VAR # accordingly. ac_fn_c_check_header_mongrel () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack if eval \${$3+:} false; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } else # Is the header compilable? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 $as_echo_n "checking $2 usability... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 #include <$2> _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_header_compiler=yes else ac_header_compiler=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 $as_echo "$ac_header_compiler" >&6; } # Is the header present? { $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 $as_echo_n "checking $2 presence... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include <$2> _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : ac_header_preproc=yes else ac_header_preproc=no fi rm -f conftest.err conftest.i conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 $as_echo "$ac_header_preproc" >&6; } # So? What about this header? case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( yes:no: ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 $as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ;; no:yes:* ) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 $as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 $as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 $as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 $as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} ( $as_echo "## -------------------------------- ## ## Report this to bugs@opendkim.org ## ## -------------------------------- ##" ) | sed "s/^/$as_me: WARNING: /" >&2 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=\$ac_header_compiler" fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } fi eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel # ac_fn_c_find_uintX_t LINENO BITS VAR # ------------------------------------ # Finds an unsigned integer type with width BITS, setting cache variable VAR # accordingly. ac_fn_c_find_uintX_t () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uint$2_t" >&5 $as_echo_n "checking for uint$2_t... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" # Order is important - never check a type that is potentially smaller # than half of the expected target width. for ac_type in uint$2_t 'unsigned int' 'unsigned long int' \ 'unsigned long long int' 'unsigned short int' 'unsigned char'; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { static int test_array [1 - 2 * !((($ac_type) -1 >> ($2 / 2 - 1)) >> ($2 / 2 - 1) == 3)]; test_array [0] = 0; return test_array [0]; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : case $ac_type in #( uint$2_t) : eval "$3=yes" ;; #( *) : eval "$3=\$ac_type" ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if eval test \"x\$"$3"\" = x"no"; then : else break fi done fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_find_uintX_t # ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES # ---------------------------------------------------- # Tries to find if the field MEMBER exists in type AGGR, after including # INCLUDES, setting cache variable VAR accordingly. ac_fn_c_check_member () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 $as_echo_n "checking for $2.$3... " >&6; } if eval \${$4+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $5 int main () { static $2 ac_aggr; if (sizeof ac_aggr.$3) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$4=yes" else eval "$4=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$4 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_member # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR # accordingly. ac_fn_c_check_decl () { as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack as_decl_name=`echo $2|sed 's/ *(.*//'` as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'` { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5 $as_echo_n "checking whether $as_decl_name is declared... " >&6; } if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $4 int main () { #ifndef $as_decl_name #ifdef __cplusplus (void) $as_decl_use; #else (void) $as_decl_name; #endif #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : eval "$3=yes" else eval "$3=no" fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_decl cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by OpenDKIM $as_me 2.11.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { cat <<_ASUNAME ## --------- ## ## Platform. ## ## --------- ## hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` uname -m = `(uname -m) 2>/dev/null || echo unknown` uname -r = `(uname -r) 2>/dev/null || echo unknown` uname -s = `(uname -s) 2>/dev/null || echo unknown` uname -v = `(uname -v) 2>/dev/null || echo unknown` /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` /bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` /bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` /usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` /usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` /bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` /bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` _ASUNAME as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. $as_echo "PATH: $as_dir" done IFS=$as_save_IFS } >&5 cat >&5 <<_ACEOF ## ----------- ## ## Core tests. ## ## ----------- ## _ACEOF # Keep a trace of the command line. # Strip out --no-create and --no-recursion so they do not pile up. # Strip out --silent because we don't want to record it for future runs. # Also quote any args containing shell meta-characters. # Make two passes to allow for proper duplicate-argument suppression. ac_configure_args= ac_configure_args0= ac_configure_args1= ac_must_keep_next=false for ac_pass in 1 2 do for ac_arg do case $ac_arg in -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil) continue ;; *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; esac case $ac_pass in 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; 2) as_fn_append ac_configure_args1 " '$ac_arg'" if test $ac_must_keep_next = true; then ac_must_keep_next=false # Got value, back to normal. else case $ac_arg in *=* | --config-cache | -C | -disable-* | --disable-* \ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ | -with-* | --with-* | -without-* | --without-* | --x) case "$ac_configure_args0 " in "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; esac ;; -* ) ac_must_keep_next=true ;; esac fi as_fn_append ac_configure_args " '$ac_arg'" ;; esac done done { ac_configure_args0=; unset ac_configure_args0;} { ac_configure_args1=; unset ac_configure_args1;} # When interrupted or exit'd, cleanup temporary files, and complete # config.log. We remove comments because anyway the quotes in there # would cause problems or look ugly. # WARNING: Use '\'' to represent an apostrophe within the trap. # WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. trap 'exit_status=$? # Save into config.log some information that might help in debugging. { echo $as_echo "## ---------------- ## ## Cache variables. ## ## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( *${as_nl}ac_space=\ *) sed -n \ "s/'\''/'\''\\\\'\'''\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" ;; #( *) sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) echo $as_echo "## ----------------- ## ## Output variables. ## ## ----------------- ##" echo for ac_var in $ac_subst_vars do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo if test -n "$ac_subst_files"; then $as_echo "## ------------------- ## ## File substitutions. ## ## ------------------- ##" echo for ac_var in $ac_subst_files do eval ac_val=\$$ac_var case $ac_val in *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; esac $as_echo "$ac_var='\''$ac_val'\''" done | sort echo fi if test -s confdefs.h; then $as_echo "## ----------- ## ## confdefs.h. ## ## ----------- ##" echo cat confdefs.h echo fi test "$ac_signal" != 0 && $as_echo "$as_me: caught signal $ac_signal" $as_echo "$as_me: exit $exit_status" } >&5 rm -f core *.core core.conftest.* && rm -f -r conftest* confdefs* conf$$* $ac_clean_files && exit $exit_status ' 0 for ac_signal in 1 2 13 15; do trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal done ac_signal=0 # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -f -r conftest* confdefs.h $as_echo "/* confdefs.h */" > confdefs.h # Predefined preprocessor variables. cat >>confdefs.h <<_ACEOF #define PACKAGE_NAME "$PACKAGE_NAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_TARNAME "$PACKAGE_TARNAME" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_VERSION "$PACKAGE_VERSION" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_STRING "$PACKAGE_STRING" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" _ACEOF cat >>confdefs.h <<_ACEOF #define PACKAGE_URL "$PACKAGE_URL" _ACEOF # Let the site file select an alternate cache file if it wants to. # Prefer an explicitly selected file to automatically selected ones. ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then # We do not want a PATH search for config.site. case $CONFIG_SITE in #(( -*) ac_site_file1=./$CONFIG_SITE;; */*) ac_site_file1=$CONFIG_SITE;; *) ac_site_file1=./$CONFIG_SITE;; esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site else ac_site_file1=$ac_default_prefix/share/config.site ac_site_file2=$ac_default_prefix/etc/config.site fi for ac_site_file in "$ac_site_file1" "$ac_site_file2" do test "x$ac_site_file" = xNONE && continue if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 . "$ac_site_file" \ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "failed to load site script $ac_site_file See \`config.log' for more details" "$LINENO" 5; } fi done if test -r "$cache_file"; then # Some versions of bash will fail to source /dev/null (special files # actually), so we avoid doing that. DJGPP emulates it as a regular file. if test /dev/null != "$cache_file" && test -f "$cache_file"; then { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 $as_echo "$as_me: loading cache $cache_file" >&6;} case $cache_file in [\\/]* | ?:[\\/]* ) . "$cache_file";; *) . "./$cache_file";; esac fi else { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi as_fn_append ac_header_list " sys/time.h" as_fn_append ac_header_list " unistd.h" as_fn_append ac_func_list " alarm" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false for ac_var in $ac_precious_vars; do eval ac_old_set=\$ac_cv_env_${ac_var}_set eval ac_new_set=\$ac_env_${ac_var}_set eval ac_old_val=\$ac_cv_env_${ac_var}_value eval ac_new_val=\$ac_env_${ac_var}_value case $ac_old_set,$ac_new_set in set,) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} ac_cache_corrupted=: ;; ,set) { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 $as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} ac_cache_corrupted=: ;; ,);; *) if test "x$ac_old_val" != "x$ac_new_val"; then # differences in whitespace do not lead to failure. ac_old_val_w=`echo x $ac_old_val` ac_new_val_w=`echo x $ac_new_val` if test "$ac_old_val_w" != "$ac_new_val_w"; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 $as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} ac_cache_corrupted=: else { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 $as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} eval $ac_var=\$ac_old_val fi { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 $as_echo "$as_me: former value: \`$ac_old_val'" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 $as_echo "$as_me: current value: \`$ac_new_val'" >&2;} fi;; esac # Pass precious variables to config.status. if test "$ac_new_set" = set; then case $ac_new_val in *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; *) ac_arg=$ac_var=$ac_new_val ;; esac case " $ac_configure_args " in *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. *) as_fn_append ac_configure_args " '$ac_arg'" ;; esac fi done if $ac_cache_corrupted; then { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## ## -------------------- ## ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_aux_dir= for ac_dir in build-aux "$srcdir"/build-aux; do if test -f "$ac_dir/install-sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install-sh -c" break elif test -f "$ac_dir/install.sh"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/install.sh -c" break elif test -f "$ac_dir/shtool"; then ac_aux_dir=$ac_dir ac_install_sh="$ac_aux_dir/shtool install -c" break fi done if test -z "$ac_aux_dir"; then as_fn_error $? "cannot find install-sh, install.sh, or shtool in build-aux \"$srcdir\"/build-aux" "$LINENO" 5 fi # These three variables are undocumented and unsupported, # and are intended to be withdrawn in a future Autoconf release. # They can cause serious problems if a builder's source tree is in a directory # whose full name contains unusual characters. ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. am__api_version='1.13' # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: # SysV /etc/install, /usr/sbin/install # SunOS /usr/etc/install # IRIX /sbin/install # AIX /bin/install # AmigaOS /C/install, which installs bootblocks on floppy discs # AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag # AFS /usr/afsws/bin/install, which mishandles nonexistent args # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # OS/2's system install, which has a completely different semantic # ./install, which can be erroneously created by make from ./install.sh. # Reject install programs that cannot install multiple files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. # Account for people who put trailing slashes in PATH elements. case $as_dir/ in #(( ./ | .// | /[cC]/* | \ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ /usr/ucb/* ) ;; *) # OSF1 and SCO ODT 3.0 have their own names for install. # Don't use installbsd from OSF since it installs stuff as root # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. : elif test $ac_prog = install && grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # program-specific install script used by HP pwplus--don't use. : else rm -rf conftest.one conftest.two conftest.dir echo one > conftest.one echo two > conftest.two mkdir conftest.dir if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && test -s conftest.one && test -s conftest.two && test -s conftest.dir/conftest.one && test -s conftest.dir/conftest.two then ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" break 3 fi fi fi done done ;; esac done IFS=$as_save_IFS rm -rf conftest.one conftest.two conftest.dir fi if test "${ac_cv_path_install+set}" = set; then INSTALL=$ac_cv_path_install else # As a last resort, use the slow shell script. Don't cache a # value for INSTALL within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. INSTALL=$ac_install_sh fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 $as_echo "$INSTALL" >&6; } # Use test -z because SunOS4 sh mishandles braces in ${var-val}. # It thinks the first close brace ends the variable substitution. test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac # Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( am_has_slept=no for am_try in 1 2; do echo "timestamp, slept: $am_has_slept" > conftest.file set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` if test "$*" = "X"; then # -L didn't work. set X `ls -t "$srcdir/configure" conftest.file` fi if test "$*" != "X $srcdir/configure conftest.file" \ && test "$*" != "X conftest.file $srcdir/configure"; then # If neither matched, then we have a broken ls. This can happen # if, for instance, CONFIG_SHELL is bash and it inherits a # broken ls alias from the environment. This has actually # happened. Such a system could not be considered "sane". as_fn_error $? "ls -t appears to fail. Make sure there is not a broken alias in your environment" "$LINENO" 5 fi if test "$2" = conftest.file || test $am_try -eq 2; then break fi # Just in case. sleep 1 am_has_slept=yes done test "$2" = conftest.file ) then # Ok. : else as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } # If we didn't sleep, we still need to ensure time stamps of config.status and # generated files are strictly newer. am_sleep_pid= if grep 'slept: no' conftest.file >/dev/null 2>&1; then ( sleep 1 ) & am_sleep_pid=$! fi rm -f conftest.file test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. test "$program_suffix" != NONE && program_transform_name="s&\$&$program_suffix&;$program_transform_name" # Double any \ or $. # By default was `s,x,x', remove it if useless. ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` # expand $ac_aux_dir to an absolute path am_aux_dir=`cd $ac_aux_dir && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in *\ * | *\ *) MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;; *) MISSING="\${SHELL} $am_aux_dir/missing" ;; esac fi # Use eval to expand $SHELL if eval "$MISSING --is-lightweight"; then am_missing_run="$MISSING " else am_missing_run= { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 $as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi if test x"${install_sh}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; *) install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi # Installed binaries are usually stripped using 'strip' when the user # run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake # will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/opt/sfw/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ 'mkdir (fileutils) '4.1*) ac_cv_path_mkdir=$as_dir/$ac_prog$ac_exec_ext break 3;; esac done done done IFS=$as_save_IFS fi test -d ./--version && rmdir ./--version if test "${ac_cv_path_mkdir+set}" = set; then MKDIR_P="$ac_cv_path_mkdir -p" else # As a last resort, use the slow shell script. Don't cache a # value for MKDIR_P within a source directory, because that will # break other packages using the cache if that directory is # removed, or if the value is a relative name. MKDIR_P="$ac_install_sh -d" fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AWK=$ac_cv_prog_AWK if test -n "$AWK"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 $as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AWK" && break done { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5 $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF # GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; *) eval ac_cv_prog_make_${ac_make}_set=no;; esac rm -f conftest.make fi if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } SET_MAKE= else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null if test -d .tst; then am__leading_dot=. else am__leading_dot=_ fi rmdir .tst 2>/dev/null # Check whether --enable-silent-rules was given. if test "${enable_silent_rules+set}" = set; then : enableval=$enable_silent_rules; fi case $enable_silent_rules in # ((( yes) AM_DEFAULT_VERBOSITY=0;; no) AM_DEFAULT_VERBOSITY=1;; *) AM_DEFAULT_VERBOSITY=1;; esac am_make=${MAKE-make} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 $as_echo_n "checking whether $am_make supports nested variables... " >&6; } if ${am_cv_make_support_nested_variables+:} false; then : $as_echo_n "(cached) " >&6 else if $as_echo 'TRUE=$(BAR$(V)) BAR0=false BAR1=true V=1 am__doit: @$(TRUE) .PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then am_cv_make_support_nested_variables=yes else am_cv_make_support_nested_variables=no fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 $as_echo "$am_cv_make_support_nested_variables" >&6; } if test $am_cv_make_support_nested_variables = yes; then AM_V='$(V)' AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' else AM_V=$AM_DEFAULT_VERBOSITY AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY fi AM_BACKSLASH='\' if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi # test whether we have cygpath if test -z "$CYGPATH_W"; then if (cygpath --version) >/dev/null 2>/dev/null; then CYGPATH_W='cygpath -w' else CYGPATH_W=echo fi fi # Define the identity of the package. PACKAGE='opendkim' VERSION='2.11.0' cat >>confdefs.h <<_ACEOF #define PACKAGE "$PACKAGE" _ACEOF cat >>confdefs.h <<_ACEOF #define VERSION "$VERSION" _ACEOF # Some tools Automake needs. ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} # For better backward compatibility. To be removed once Automake 1.9.x # dies out for good. For more background, see: # # mkdir_p='$(MKDIR_P)' # We need awk for the "check" target. The system "awk" is bad on # some platforms. # Always define AMTAR for backward compatibility. Yes, it's still used # in the wild :-( We should find a proper way to deprecate it ... AMTAR='$${TAR-tar}' # We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar pax cpio none' am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' ac_config_headers="$ac_config_headers build-config.h" # # Hexadecimal version, for use in generating dkim.h # HEX_VERSION=$(printf %08x $(( ((2 << 8 | 11) << 8 | 0) << 8| 0 ))) # # library version, passed to libtool # LIBOPENDKIM_VERSION_INFO=$(printf %d:%d:%d 11 0 0) # # Checks for programs # ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_CC"; then ac_ct_CC=$CC # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi else CC="$ac_cv_prog_CC" fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi fi if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else ac_prog_rejected=no as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue fi ac_cv_prog_CC="cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS if test $ac_prog_rejected = yes; then # We found a bogon in the path, so make sure we never use it. set dummy $ac_cv_prog_CC shift if test $# != 0; then # We chose a different compiler from the bogus one. # However, it has the same basename, so the bogon will be chosen # first if we set CC to just the basename; use the full file name. shift ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" fi fi fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$CC"; then if test -n "$ac_tool_prefix"; then for ac_prog in cl.exe do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then ac_cv_prog_CC="$CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi CC=$ac_cv_prog_CC if test -n "$CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 $as_echo "$CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$CC" && break done fi if test -z "$CC"; then ac_ct_CC=$CC for ac_prog in cl.exe do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_CC=$ac_cv_prog_ac_ct_CC if test -n "$ac_ct_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 $as_echo "$ac_ct_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_CC" && break done if test "x$ac_ct_CC" = x; then CC="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac CC=$ac_ct_CC fi fi fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "no acceptable C compiler found in \$PATH See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 set X $ac_compile ac_compiler=$2 for ac_option in --version -v -V -qversion; do { { ac_try="$ac_compiler $ac_option >&5" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compiler $ac_option >&5") 2>conftest.err ac_status=$? if test -s conftest.err; then sed '10a\ ... rest of stderr output deleted ... 10q' conftest.err >conftest.er1 cat conftest.er1 >&5 fi rm -f conftest.er1 conftest.err $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } done cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" # Try to create an executable without -o first, disregard a.out. # It will help us diagnose broken compilers, and finding out an intuition # of exeext. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 $as_echo_n "checking whether the C compiler works... " >&6; } ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` # The possible output files: ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" ac_rmfiles= for ac_file in $ac_files do case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; * ) ac_rmfiles="$ac_rmfiles $ac_file";; esac done rm -f $ac_rmfiles if { { ac_try="$ac_link_default" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link_default") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. # So ignore a value of `no', otherwise this would lead to `EXEEXT = no' # in a Makefile. We should not override ac_cv_exeext if it was cached, # so that the user can short-circuit this test for compilers unknown to # Autoconf. for ac_file in $ac_files '' do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; [ab].out ) # We found the default executable, but exeext='' is most # certainly right. break;; *.* ) if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; then :; else ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` fi # We set ac_cv_exeext here because the later test for it is not # safe: cross compilers may not add the suffix if given an `-o' # argument, so we may need to know it at that point already. # Even if this section looks crufty: it has the advantage of # actually working. break;; * ) break;; esac done test "$ac_cv_exeext" = no && ac_cv_exeext= else ac_file='' fi if test -z "$ac_file"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error 77 "C compiler cannot create executables See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 $as_echo_n "checking for C compiler default output file name... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 $as_echo "$ac_file" >&6; } ac_exeext=$ac_cv_exeext rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 $as_echo_n "checking for suffix of executables... " >&6; } if { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : # If both `conftest.exe' and `conftest' are `present' (well, observable) # catch `conftest.exe'. For instance with Cygwin, `ls conftest' will # work properly (i.e., refer to `conftest.exe'), while it won't with # `rm'. for ac_file in conftest.exe conftest conftest.*; do test -f "$ac_file" || continue case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` break;; * ) break;; esac done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of executables: cannot compile and link See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 $as_echo "$ac_cv_exeext" >&6; } rm -f conftest.$ac_ext EXEEXT=$ac_cv_exeext ac_exeext=$EXEEXT cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { FILE *f = fopen ("conftest.out", "w"); return ferror (f) || fclose (f) != 0; ; return 0; } _ACEOF ac_clean_files="$ac_clean_files conftest.out" # Check that the compiler produces executables we can run. If not, either # the compiler is broken, or we cross compile. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 $as_echo_n "checking whether we are cross compiling... " >&6; } if test "$cross_compiling" != yes; then { { ac_try="$ac_link" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_link") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if { ac_try='./conftest$ac_cv_exeext' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then cross_compiling=no else if test "$cross_compiling" = maybe; then cross_compiling=yes else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. See \`config.log' for more details" "$LINENO" 5; } fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 $as_echo "$cross_compiling" >&6; } rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF rm -f conftest.o conftest.obj if { { ac_try="$ac_compile" case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_compile") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then : for ac_file in conftest.o conftest.obj conftest.*; do test -f "$ac_file" || continue; case $ac_file in *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` break;; esac done else $as_echo "$as_me: failed program was:" >&5 sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot compute suffix of object files: cannot compile See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 $as_echo "$ac_cv_objext" >&6; } OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { #ifndef __GNUC__ choke me #endif ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_compiler_gnu=yes else ac_compiler_gnu=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_cv_c_compiler_gnu=$ac_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 $as_echo "$ac_cv_c_compiler_gnu" >&6; } if test $ac_compiler_gnu = yes; then GCC=yes else GCC= fi ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag ac_c_werror_flag=yes ac_cv_prog_cc_g=no CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes else CFLAGS="" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : else ac_c_werror_flag=$ac_save_c_werror_flag CFLAGS="-g" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_g=yes fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext ac_c_werror_flag=$ac_save_c_werror_flag fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 $as_echo "$ac_cv_prog_cc_g" >&6; } if test "$ac_test_CFLAGS" = set; then CFLAGS=$ac_save_CFLAGS elif test $ac_cv_prog_cc_g = yes; then if test "$GCC" = yes; then CFLAGS="-g -O2" else CFLAGS="-g" fi else if test "$GCC" = yes; then CFLAGS="-O2" else CFLAGS= fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); static char *e (p, i) char **p; int i; { return p[i]; } static char *f (char * (*g) (char **, int), char **p, ...) { char *s; va_list v; va_start (v,p); s = g (p, va_arg (v,int)); va_end (v); return s; } /* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has function prototypes and stuff, but not '\xHH' hex character constants. These don't provoke an error unfortunately, instead are silently treated as 'x'. The following induces an error, until -std is added to get proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an array size at least. It's necessary to write '\x00'==0 to get something that's true only with -std. */ int osf4_cc_array ['\x00' == 0 ? 1 : -1]; /* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters inside strings and character constants. */ #define FOO(x) 'x' int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; int test (int i, double x); struct s1 {int (*f) (int a);}; struct s2 {int (*f) (double a);}; int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); int argc; char **argv; int main () { return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } _ACEOF for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c89=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c89" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c89" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c89" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 $as_echo "$ac_cv_prog_cc_c89" >&6; } ;; esac if test "x$ac_cv_prog_cc_c89" != xno; then : fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" am_make=${MAKE-make} cat > confinc << 'END' am__doit: @echo this is the am__doit target .PHONY: am__doit END # If we don't find an include directive, just comment out the code. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 $as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= _am_result=none # First try GNU make style include. echo "include confinc" > confmf # Ignore all kinds of additional output from 'make'. case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=include am__quote= _am_result=GNU ;; esac # Now try BSD make style include. if test "$am__include" = "#"; then echo '.include "confinc"' > confmf case `$am_make -s -f confmf 2> /dev/null` in #( *the\ am__doit\ target*) am__include=.include am__quote="\"" _am_result=BSD ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 $as_echo "$_am_result" >&6; } rm -f confinc confmf # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : enableval=$enable_dependency_tracking; fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= AMDEP_FALSE='#' else AMDEP_TRUE='#' AMDEP_FALSE= fi depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up # making a dummy file named 'D' -- because '-MD' means "put the output # in D". rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. cp "$am_depcomp" conftest.dir cd conftest.dir # We will build objects and dependencies in a subdirectory because # it helps to detect inapplicable dependency modes. For instance # both Tru64's cc and ICC support -MD to output dependencies as a # side effect of compilation, but ICC will put the dependencies in # the current directory while Tru64 will put them in the object # directory. mkdir sub am_cv_CC_dependencies_compiler_type=none if test "$am_compiler_list" = ""; then am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` fi am__universal=false case " $depcc " in #( *\ -arch\ *\ -arch\ *) am__universal=true ;; esac for depmode in $am_compiler_list; do # Setup a source with many dependencies, because some compilers # like to wrap large dependency lists on column 80 (with \), and # we should not choose a depcomp mode which is confused by this. # # We need to recreate these files for each test, as the compiler may # overwrite some of them when testing with obscure command lines. # This happens at least with the AIX C compiler. : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with # Solaris 10 /bin/sh. echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly # handle '-M -o', and we need to detect this. Also, some Intel # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in gcc) # This depmode causes a compiler race in universal mode. test "$am__universal" = false || continue ;; nosideeffect) # After this tag, mechanisms are not by side-effect, so they'll # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; msvc7 | msvc7msys | msvisualcpp | msvcmsys) # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} am__minus_obj= ;; none) break ;; esac if depmode=$depmode \ source=sub/conftest.c object=$am__obj \ depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ >/dev/null 2>conftest.err && grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && grep $am__obj sub/conftest.Po > /dev/null 2>&1 && ${MAKE-make} -s -f confmf > /dev/null 2>&1; then # icc doesn't choke on unknown options, it will just issue warnings # or remarks (even with -Werror). So we grep stderr for any message # that says an option was ignored or not supported. # When given -MP, icc 7.0 and 7.1 complain thusly: # icc: Command line warning: ignoring option '-M'; no argument required # The diagnosis changed in icc 8.0: # icc: Command line remark: option '-MP' not supported if (grep 'ignoring option' conftest.err || grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else am_cv_CC_dependencies_compiler_type=$depmode break fi fi done cd .. rm -rf conftest.dir else am_cv_CC_dependencies_compiler_type=none fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CC_dependencies_compiler_type" >&5 $as_echo "$am_cv_CC_dependencies_compiler_type" >&6; } CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type if test "x$enable_dependency_tracking" != xno \ && test "$am_cv_CC_dependencies_compiler_type" = gcc3; then am__fastdepCC_TRUE= am__fastdepCC_FALSE='#' else am__fastdepCC_TRUE='#' am__fastdepCC_FALSE= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5 $as_echo_n "checking for $CC option to accept ISO C99... " >&6; } if ${ac_cv_prog_cc_c99+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c99=no ac_save_CC=$CC cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include #include // Check varargs macros. These examples are taken from C99 6.10.3.5. #define debug(...) fprintf (stderr, __VA_ARGS__) #define showlist(...) puts (#__VA_ARGS__) #define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__)) static void test_varargs_macros (void) { int x = 1234; int y = 5678; debug ("Flag"); debug ("X = %d\n", x); showlist (The first, second, and third items.); report (x>y, "x is %d but y is %d", x, y); } // Check long long types. #define BIG64 18446744073709551615ull #define BIG32 4294967295ul #define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0) #if !BIG_OK your preprocessor is broken; #endif #if BIG_OK #else your preprocessor is broken; #endif static long long int bignum = -9223372036854775807LL; static unsigned long long int ubignum = BIG64; struct incomplete_array { int datasize; double data[]; }; struct named_init { int number; const wchar_t *name; double average; }; typedef const char *ccp; static inline int test_restrict (ccp restrict text) { // See if C++-style comments work. // Iterate through items via the restricted pointer. // Also check for declarations in for loops. for (unsigned int i = 0; *(text+i) != '\0'; ++i) continue; return 0; } // Check varargs and va_copy. static void test_varargs (const char *format, ...) { va_list args; va_start (args, format); va_list args_copy; va_copy (args_copy, args); const char *str; int number; float fnumber; while (*format) { switch (*format++) { case 's': // string str = va_arg (args_copy, const char *); break; case 'd': // int number = va_arg (args_copy, int); break; case 'f': // float fnumber = va_arg (args_copy, double); break; default: break; } } va_end (args_copy); va_end (args); } int main () { // Check bool. _Bool success = false; // Check restrict. if (test_restrict ("String literal") == 0) success = true; char *restrict newvar = "Another string"; // Check varargs. test_varargs ("s, d' f .", "string", 65, 34.234); test_varargs_macros (); // Check flexible array members. struct incomplete_array *ia = malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10)); ia->datasize = 10; for (int i = 0; i < ia->datasize; ++i) ia->data[i] = i * 1.234; // Check named initializers. struct named_init ni = { .number = 34, .name = L"Test wide string", .average = 543.34343, }; ni.number = 58; int dynamic_array[ni.number]; dynamic_array[ni.number - 1] = 543; // work around unused variable warnings return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x' || dynamic_array[ni.number - 1] != 543); ; return 0; } _ACEOF for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99 do CC="$ac_save_CC $ac_arg" if ac_fn_c_try_compile "$LINENO"; then : ac_cv_prog_cc_c99=$ac_arg fi rm -f core conftest.err conftest.$ac_objext test "x$ac_cv_prog_cc_c99" != "xno" && break done rm -f conftest.$ac_ext CC=$ac_save_CC fi # AC_CACHE_VAL case "x$ac_cv_prog_cc_c99" in x) { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 $as_echo "none needed" >&6; } ;; xno) { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 $as_echo "unsupported" >&6; } ;; *) CC="$CC $ac_cv_prog_cc_c99" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5 $as_echo "$ac_cv_prog_cc_c99" >&6; } ;; esac if test "x$ac_cv_prog_cc_c99" != xno; then : fi if test "x$CC" != xcc; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5 $as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5 $as_echo_n "checking whether cc understands -c and -o together... " >&6; } fi set dummy $CC; ac_cc=`$as_echo "$2" | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` if eval \${ac_cv_prog_cc_${ac_cc}_c_o+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF # Make sure it works both with $CC and with simple cc. # We do the test twice because some compilers refuse to overwrite an # existing .o file with -o, though they will create one. ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then eval ac_cv_prog_cc_${ac_cc}_c_o=yes if test "x$CC" != xcc; then # Test first that cc exists at all. if { ac_try='cc -c conftest.$ac_ext >&5' { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; }; then ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5' rm -f conftest2.* if { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -f conftest2.$ac_objext && { { case "(($ac_try" in *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; *) ac_try_echo=$ac_try;; esac eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" $as_echo "$ac_try_echo"; } >&5 (eval "$ac_try") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # cc works too. : else # cc exists but doesn't like -o. eval ac_cv_prog_cc_${ac_cc}_c_o=no fi fi fi else eval ac_cv_prog_cc_${ac_cc}_c_o=no fi rm -f core conftest* fi if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } $as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h fi # FIXME: we rely on the cache variable name because # there is no other way. set dummy $CC am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'` eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o if test "$am_t" != yes; then # Losing compiler, so override with the script. # FIXME: It is wrong to rewrite CC. # But if we don't then we get into trouble of one sort or another. # A longer-term fix would be to have automake use am__CC in this case, # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" CC="$am_aux_dir/compile $CC" fi case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 $as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; esac macro_version='2.4' macro_revision='1.3293' ltmain="$ac_aux_dir/ltmain.sh" # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; *) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' set x $ac_cv_build shift build_cpu=$1 build_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: build_os=$* IFS=$ac_save_IFS case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; *) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' set x $ac_cv_host shift host_cpu=$1 host_vendor=$2 shift; shift # Remember, the first character of IFS is used to create $*, # except with old shells: host_os=$* IFS=$ac_save_IFS case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac # Backslashify metacharacters that are still active within # double-quoted strings. sed_quote_subst='s/\(["`$\\]\)/\\\1/g' # Same as above, but do not quote variable references. double_quote_subst='s/\(["`\\]\)/\\\1/g' # Sed substitution to delay expansion of an escaped shell variable in a # double_quote_subst'ed string. delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' # Sed substitution to delay expansion of an escaped single quote. delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' # Sed substitution to avoid accidental globbing in evaled expressions no_glob_subst='s/\*/\\\*/g' ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 $as_echo_n "checking how to print strings... " >&6; } # Test print first, because it will be a builtin if present. if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='print -r --' elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then ECHO='printf %s\n' else # Use this function as a fallback that always works. func_fallback_echo () { eval 'cat <<_LTECHO_EOF $1 _LTECHO_EOF' } ECHO='func_fallback_echo' fi # func_echo_all arg... # Invoke $ECHO with all args, space-separated. func_echo_all () { $ECHO "" } case "$ECHO" in printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 $as_echo "printf" >&6; } ;; print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 $as_echo "print -r" >&6; } ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 $as_echo "cat" >&6; } ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ for ac_i in 1 2 3 4 5 6 7; do ac_script="$ac_script$as_nl$ac_script" done echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed { ac_script=; unset ac_script;} if test -z "$SED"; then ac_path_SED_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in *GNU*) ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo '' >> "conftest.nl" "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_SED_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_SED="$ac_path_SED" ac_path_SED_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_SED_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 $as_echo "$ac_cv_path_SED" >&6; } SED="$ac_cv_path_SED" rm -f conftest.sed test -z "$SED" && SED=sed Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then ac_path_GREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in *GNU*) ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'GREP' >> "conftest.nl" "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_GREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_GREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 $as_echo "$ac_cv_path_GREP" >&6; } GREP="$ac_cv_path_GREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 then ac_cv_path_EGREP="$GREP -E" else if test -z "$EGREP"; then ac_path_EGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in *GNU*) ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'EGREP' >> "conftest.nl" "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_EGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_EGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 $as_echo "$ac_cv_path_EGREP" >&6; } EGREP="$ac_cv_path_EGREP" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 then ac_cv_path_FGREP="$GREP -F" else if test -z "$FGREP"; then ac_path_FGREP_found=false # Loop through the user's path and test for each of PROGNAME-LIST as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in *GNU*) ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; *) ac_count=0 $as_echo_n 0123456789 >"conftest.in" while : do cat "conftest.in" "conftest.in" >"conftest.tmp" mv "conftest.tmp" "conftest.in" cp "conftest.in" "conftest.nl" $as_echo 'FGREP' >> "conftest.nl" "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break as_fn_arith $ac_count + 1 && ac_count=$as_val if test $ac_count -gt ${ac_path_FGREP_max-0}; then # Best one so far, save it but keep looking for a better one ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_max=$ac_count fi # 10*(2^10) chars as input seems more than enough test $ac_count -gt 10 && break done rm -f conftest.in conftest.tmp conftest.nl conftest.out;; esac $ac_path_FGREP_found && break 3 done done done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 $as_echo "$ac_cv_path_FGREP" >&6; } FGREP="$ac_cv_path_FGREP" test -z "$GREP" && GREP=grep # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld if test "$GCC" = yes; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) # gcc leaves a trailing carriage return which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; esac case $ac_prog in # Accept absolute paths. [\\/]* | ?:[\\/]*) re_direlt='/[^/][^/]*/\.\./' # Canonicalize the pathname of ld ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done test -z "$LD" && LD="$ac_prog" ;; "") # If it fails, then pretend we aren't using GCC. ac_prog=ld ;; *) # If it is relative, then search for the first ld in PATH. with_gnu_ld=unknown ;; esac elif test "$with_gnu_ld" = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then lt_cv_path_LD="$ac_dir/$ac_prog" # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. case `$LD -v 2>&1 &5 $as_echo "$lt_cv_prog_gnu_ld" >&6; } with_gnu_ld=$lt_cv_prog_gnu_ld { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. lt_cv_path_NM="$NM" else lt_nm_to_check="${ac_tool_prefix}nm" if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. tmp_nm="$ac_dir/$lt_tmp_nm" if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then # Check to see if the nm accepts a BSD-compat flag. # Adding the `sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in */dev/null* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" break ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" break ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but continue # so that we can try to find one that supports BSD flags ;; esac ;; esac fi done IFS="$lt_save_ifs" done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. if test -n "$DUMPBIN"; then : # Let the user override the test. else if test -n "$ac_tool_prefix"; then for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then ac_cv_prog_DUMPBIN="$DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DUMPBIN=$ac_cv_prog_DUMPBIN if test -n "$DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 $as_echo "$DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$DUMPBIN" && break done fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN if test -n "$ac_ct_DUMPBIN"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 $as_echo "$ac_ct_DUMPBIN" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_DUMPBIN" && break done if test "x$ac_ct_DUMPBIN" = x; then DUMPBIN=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DUMPBIN=$ac_ct_DUMPBIN fi fi case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in *COFF*) DUMPBIN="$DUMPBIN -symbols" ;; *) DUMPBIN=: ;; esac fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" fi fi test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 $as_echo "$lt_cv_nm_interface" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 $as_echo_n "checking whether ln -s works... " >&6; } LN_S=$as_ln_s if test "$LN_S" = "ln -s"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 $as_echo "no, using $LN_S" >&6; } fi # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 teststring="ABCD" case $build_os in msdosdjgpp*) # On DJGPP, this test can blow up pretty badly due to problems in libc # (any single argument exceeding 2000 bytes causes a buffer overrun # during glob expansion). Even if it were fixed, the result of this # check would be larger than it should be. lt_cv_sys_max_cmd_len=12288; # 12K is about right ;; gnu*) # Under GNU Hurd, this test is not required because there is # no limit to the length of command line arguments. # Libtool will interpret -1 as no limit whatsoever lt_cv_sys_max_cmd_len=-1; ;; cygwin* | mingw* | cegcc*) # On Win9x/ME, this test blows up -- it succeeds, but takes # about 5 minutes as the teststring grows exponentially. # Worse, since 9x/ME are not pre-emptively multitasking, # you end up with a "frozen" computer, even though with patience # the test eventually succeeds (with a max line length of 256k). # Instead, let's just punt: use the minimum linelength reported by # all of the supported platforms: 8192 (on NT/2K/XP). lt_cv_sys_max_cmd_len=8192; ;; mint*) # On MiNT this can take a long time and run out of memory. lt_cv_sys_max_cmd_len=8192; ;; amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` elif test -x /usr/sbin/sysctl; then lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` else lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs fi # And add a safety zone lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` ;; interix*) # We know the value 262144 and hardcode it with a safety zone (like BSD) lt_cv_sys_max_cmd_len=196608 ;; osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not # nice to cause kernel panics so lets avoid the loop below. # First set a reasonable default. lt_cv_sys_max_cmd_len=16384 # if test -x /sbin/sysconfig; then case `/sbin/sysconfig -q proc exec_disable_arg_limit` in *1*) lt_cv_sys_max_cmd_len=-1 ;; esac fi ;; sco3.2v5*) lt_cv_sys_max_cmd_len=102400 ;; sysv5* | sco5v6* | sysv4.2uw2*) kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` if test -n "$kargmax"; then lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` else lt_cv_sys_max_cmd_len=32768 fi ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` if test -n "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. for i in 1 2 3 4 5 6 7 8 ; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring done # Only check the string length outside the loop. lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` teststring= # Add a significant safety factor because C++ compilers can tack on # massive amounts of additional arguments before passing them to the # linker. It appears as though 1/2 is a usable value. lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` fi ;; esac fi if test -n $lt_cv_sys_max_cmd_len ; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 $as_echo "none" >&6; } fi max_cmd_len=$lt_cv_sys_max_cmd_len : ${CP="cp -f"} : ${MV="mv -f"} : ${RM="rm -f"} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 $as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } # Try some XSI features xsi_shell=no ( _lt_dummy="a/b/c" test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ = c,a/b,b/c, \ && eval 'test $(( 1 + 1 )) -eq 2 \ && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ && xsi_shell=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 $as_echo "$xsi_shell" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 $as_echo_n "checking whether the shell understands \"+=\"... " >&6; } lt_shell_append=no ( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ >/dev/null 2>&1 \ && lt_shell_append=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 $as_echo "$lt_shell_append" >&6; } if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else lt_unset=false fi # test EBCDIC or ASCII case `echo X|tr X '\101'` in A) # ASCII based system # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr lt_SP2NL='tr \040 \012' lt_NL2SP='tr \015\012 \040\040' ;; *) # EBCDIC based system lt_SP2NL='tr \100 \n' lt_NL2SP='tr \r\n \100\100' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 $as_echo_n "checking how to convert $build file names to $host format... " >&6; } if ${lt_cv_to_host_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 ;; esac ;; *-*-cygwin* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin ;; *-*-cygwin* ) lt_cv_to_host_file_cmd=func_convert_file_noop ;; * ) # otherwise, assume *nix lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin ;; esac ;; * ) # unhandled hosts (and "normal" native builds) lt_cv_to_host_file_cmd=func_convert_file_noop ;; esac fi to_host_file_cmd=$lt_cv_to_host_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 $as_echo "$lt_cv_to_host_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 $as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } if ${lt_cv_to_tool_file_cmd+:} false; then : $as_echo_n "(cached) " >&6 else #assume ordinary cross tools, or native build. lt_cv_to_tool_file_cmd=func_convert_file_noop case $host in *-*-mingw* ) case $build in *-*-mingw* ) # actually msys lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 ;; esac ;; esac fi to_tool_file_cmd=$lt_cv_to_tool_file_cmd { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 $as_echo "$lt_cv_to_tool_file_cmd" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 $as_echo "$lt_cv_ld_reload_flag" >&6; } reload_flag=$lt_cv_ld_reload_flag case $reload_flag in "" | " "*) ;; *) reload_flag=" $reload_flag" ;; esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in cygwin* | mingw* | pw32* | cegcc*) if test "$GCC" != yes; then reload_cmds=false fi ;; darwin*) if test "$GCC" = yes; then reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi ;; esac if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OBJDUMP=$ac_cv_prog_OBJDUMP if test -n "$OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 $as_echo "$OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OBJDUMP"; then ac_ct_OBJDUMP=$OBJDUMP # Extract the first word of "objdump", so it can be a program name with args. set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP if test -n "$ac_ct_OBJDUMP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 $as_echo "$ac_ct_OBJDUMP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OBJDUMP" = x; then OBJDUMP="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OBJDUMP=$ac_ct_OBJDUMP fi else OBJDUMP="$ac_cv_prog_OBJDUMP" fi test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' lt_cv_file_magic_test_file= lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. # `unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path # which responds to the $file_magic_cmd with a given extended regex. # If you have `file' or equivalent on your system and you're not sure # whether `pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) lt_cv_deplibs_check_method=pass_all ;; beos*) lt_cv_deplibs_check_method=pass_all ;; bsdi[45]*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' lt_cv_file_magic_cmd='/usr/bin/file -L' lt_cv_file_magic_test_file=/shlib/libc.so ;; cygwin*) # func_win32_libid is a shell function defined in ltmain.sh lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' ;; mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else # Keep this pattern in sync with the one in func_win32_libid. lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' ;; darwin* | rhapsody*) lt_cv_deplibs_check_method=pass_all ;; freebsd* | dragonfly*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then case $host_cpu in i*86 ) # Not sure whether the presence of OpenBSD here was a mistake. # Let's accept both of them until this is cleared up. lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` ;; esac else lt_cv_deplibs_check_method=pass_all fi ;; gnu*) lt_cv_deplibs_check_method=pass_all ;; haiku*) lt_cv_deplibs_check_method=pass_all ;; hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in ia64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac ;; interix[3-9]*) # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' ;; irix5* | irix6* | nonstopux*) case $LD in *-32|*"-32 ") libmagic=32-bit;; *-n32|*"-n32 ") libmagic=N32;; *-64|*"-64 ") libmagic=64-bit;; *) libmagic=never-match;; esac lt_cv_deplibs_check_method=pass_all ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' fi ;; newos6*) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' lt_cv_file_magic_cmd=/usr/bin/file lt_cv_file_magic_test_file=/usr/lib/libnls.so ;; *nto* | *qnx*) lt_cv_deplibs_check_method=pass_all ;; openbsd*) if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' fi ;; osf3* | osf4* | osf5*) lt_cv_deplibs_check_method=pass_all ;; rdos*) lt_cv_deplibs_check_method=pass_all ;; solaris*) lt_cv_deplibs_check_method=pass_all ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) lt_cv_deplibs_check_method=pass_all ;; sysv4 | sysv4.3*) case $host_vendor in motorola) lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` ;; ncr) lt_cv_deplibs_check_method=pass_all ;; sequent) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; sni) lt_cv_file_magic_cmd='/bin/file' lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" lt_cv_file_magic_test_file=/lib/libc.so ;; siemens) lt_cv_deplibs_check_method=pass_all ;; pc) lt_cv_deplibs_check_method=pass_all ;; esac ;; tpf*) lt_cv_deplibs_check_method=pass_all ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } file_magic_glob= want_nocaseglob=no if test "$build" = "$host"; then case $host_os in mingw* | pw32*) if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then want_nocaseglob=yes else file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` fi ;; esac fi file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DLLTOOL"; then ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DLLTOOL=$ac_cv_prog_DLLTOOL if test -n "$DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 $as_echo "$DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DLLTOOL"; then ac_ct_DLLTOOL=$DLLTOOL # Extract the first word of "dlltool", so it can be a program name with args. set dummy dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DLLTOOL"; then ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DLLTOOL="dlltool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL if test -n "$ac_ct_DLLTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 $as_echo "$ac_ct_DLLTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DLLTOOL" = x; then DLLTOOL="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DLLTOOL=$ac_ct_DLLTOOL fi else DLLTOOL="$ac_cv_prog_DLLTOOL" fi test -z "$DLLTOOL" && DLLTOOL=dlltool { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 $as_echo_n "checking how to associate runtime and link libraries... " >&6; } if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_sharedlib_from_linklib_cmd='unknown' case $host_os in cygwin* | mingw* | pw32* | cegcc*) # two different shell functions defined in ltmain.sh # decide which to use based on capabilities of $DLLTOOL case `$DLLTOOL --help 2>&1` in *--identify-strict*) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib ;; *) lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback ;; esac ;; *) # fallback: assume linklib IS sharedlib lt_cv_sharedlib_from_linklib_cmd="$ECHO" ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 $as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO if test -n "$ac_tool_prefix"; then for ac_prog in ar do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then ac_cv_prog_AR="$AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi AR=$ac_cv_prog_AR if test -n "$AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 $as_echo "$AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$AR" && break done fi if test -z "$AR"; then ac_ct_AR=$AR for ac_prog in ar do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_AR=$ac_cv_prog_ac_ct_AR if test -n "$ac_ct_AR"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 $as_echo "$ac_ct_AR" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$ac_ct_AR" && break done if test "x$ac_ct_AR" = x; then AR="false" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi fi : ${AR=ar} : ${AR_FLAGS=cru} { $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 $as_echo_n "checking for archiver @FILE support... " >&6; } if ${lt_cv_ar_at_file+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ar_at_file=no cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : echo conftest.$ac_objext > conftest.lst lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -eq 0; then # Ensure the archiver fails upon bogus file names. rm -f conftest.$ac_objext libconftest.a { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 (eval $lt_ar_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } if test "$ac_status" -ne 0; then lt_cv_ar_at_file=@ fi fi rm -f conftest.* libconftest.a fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 $as_echo "$lt_cv_ar_at_file" >&6; } if test "x$lt_cv_ar_at_file" = xno; then archiver_list_spec= else archiver_list_spec=$lt_cv_ar_at_file fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then ac_cv_prog_STRIP="$STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi STRIP=$ac_cv_prog_STRIP if test -n "$STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 $as_echo "$STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_STRIP"; then ac_ct_STRIP=$STRIP # Extract the first word of "strip", so it can be a program name with args. set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP if test -n "$ac_ct_STRIP"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 $as_echo "$ac_ct_STRIP" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_STRIP" = x; then STRIP=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac STRIP=$ac_ct_STRIP fi else STRIP="$ac_cv_prog_STRIP" fi test -z "$STRIP" && STRIP=: if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi RANLIB=$ac_cv_prog_RANLIB if test -n "$RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 $as_echo "$RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_RANLIB"; then ac_ct_RANLIB=$RANLIB # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB if test -n "$ac_ct_RANLIB"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 $as_echo "$ac_ct_RANLIB" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_RANLIB" = x; then RANLIB=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac RANLIB=$ac_ct_RANLIB fi else RANLIB="$ac_cv_prog_RANLIB" fi test -z "$RANLIB" && RANLIB=: # Determine commands to create old-style static archives. old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' old_postinstall_cmds='chmod 644 $oldlib' old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in openbsd*) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" ;; *) old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" ;; esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi case $host_os in darwin*) lock_old_archive_extraction=yes ;; *) lock_old_archive_extraction=no ;; esac # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else # These are sane defaults that work on at least a few old systems. # [They come from Ultrix. What could be older than Ultrix?!! ;)] # Character class describing NM global symbol codes. symcode='[BCDEGRST]' # Regexp to match symbols that can be accessed directly from C. sympat='\([_A-Za-z][_A-Za-z0-9]*\)' # Define system-specific variables. case $host_os in aix*) symcode='[BCDT]' ;; cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) if test "$host_cpu" = ia64; then symcode='[ABCDEGRST]' fi ;; irix* | nonstopux*) symcode='[BCDEGRST]' ;; osf*) symcode='[BCDEGQRST]' ;; solaris*) symcode='[BDRT]' ;; sco3.2v5*) symcode='[DT]' ;; sysv4.2uw2*) symcode='[DT]' ;; sysv5* | sco5v6* | unixware* | OpenUNIX*) symcode='[ABDT]' ;; sysv4) symcode='[DFNSTU]' ;; esac # If we're using GNU nm, then use its standard symbol codes. case `$NM -V 2>&1` in *GNU* | *'with BFD'*) symcode='[ABCDGIRSTW]' ;; esac # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" # Handle CRLF in mingw tool chain opt_cr= case $build_os in mingw*) opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp ;; esac # Try without a prefix underscore, then with it. for ac_symprfx in "" "_"; do # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. symxfrm="\\1 $ac_symprfx\\2 \\2" # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then # Fake it for dumpbin and say T for any non-static function # and D for any global variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ " {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ " {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ " s[1]~/^[@?]/{print s[1], s[1]; next};"\ " s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no rm -f conftest* cat > conftest.$ac_ext <<_LT_EOF #ifdef __cplusplus extern "C" { #endif char nm_test_var; void nm_test_func(void); void nm_test_func(void){} #ifdef __cplusplus } #endif int main(){nm_test_var='a';nm_test_func();return(0);} _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" else rm -f "$nlist"T fi # Make sure that we snagged all the symbols we need. if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext /* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ #if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */ # define LT_DLSYM_CONST #elif defined(__osf__) /* This system does not cope well with relocations in const data. */ # define LT_DLSYM_CONST #else # define LT_DLSYM_CONST const #endif #ifdef __cplusplus extern "C" { #endif _LT_EOF # Now generate the symbol file. eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ LT_DLSYM_CONST struct { const char *name; void *address; } lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; /* This works around a problem in FreeBSD linker */ #ifdef FREEBSD_WORKAROUND static const void *lt_preloaded_setup() { return lt__PROGRAM__LTX_preloaded_symbols; } #endif #ifdef __cplusplus } #endif _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext lt_globsym_save_LIBS=$LIBS lt_globsym_save_CFLAGS=$CFLAGS LIBS="conftstm.$ac_objext" CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext}; then pipe_works=yes fi LIBS=$lt_globsym_save_LIBS CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi else echo "cannot find nm_test_var in $nlist" >&5 fi else echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 fi else echo "$progname: failed program was:" >&5 cat conftest.$ac_ext >&5 fi rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. if test "$pipe_works" = yes; then break else lt_cv_sys_global_symbol_pipe= fi done fi if test -z "$lt_cv_sys_global_symbol_pipe"; then lt_cv_sys_global_symbol_to_cdecl= fi if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 $as_echo "failed" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } fi # Response file support. if test "$lt_cv_nm_interface" = "MS dumpbin"; then nm_file_list_spec='@' elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then nm_file_list_spec='@' fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 $as_echo_n "checking for sysroot... " >&6; } # Check whether --with-sysroot was given. if test "${with_sysroot+set}" = set; then : withval=$with_sysroot; else with_sysroot=no fi lt_sysroot= case ${with_sysroot} in #( yes) if test "$GCC" = yes; then lt_sysroot=`$CC --print-sysroot 2>/dev/null` fi ;; #( /*) lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` ;; #( no|'') ;; #( *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 $as_echo "${with_sysroot}" >&6; } as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 $as_echo "${lt_sysroot:-no}" >&6; } # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) HPUX_IA64_MODE="32" ;; *ELF-64*) HPUX_IA64_MODE="64" ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" ;; *N32*) LD="${LD-ld} -melf32bmipn32" ;; *64-bit*) LD="${LD-ld} -melf64bmip" ;; esac else case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -32" ;; *N32*) LD="${LD-ld} -n32" ;; *64-bit*) LD="${LD-ld} -64" ;; esac fi fi rm -rf conftest* ;; x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *32-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_i386" ;; ppc64-*linux*|powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) LD="${LD-ld} -m elf_s390" ;; sparc64-*linux*) LD="${LD-ld} -m elf32_sparc" ;; esac ;; *64-bit*) case $host in x86_64-*kfreebsd*-gnu) LD="${LD-ld} -m elf_x86_64_fbsd" ;; x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; ppc*-*linux*|powerpc*-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) LD="${LD-ld} -m elf64_s390" ;; sparc*-*linux*) LD="${LD-ld} -m elf64_sparc" ;; esac ;; esac fi rm -rf conftest* ;; *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. SAVE_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_cc_needs_belf=yes else lt_cv_cc_needs_belf=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } if test x"$lt_cv_cc_needs_belf" != x"yes"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf CFLAGS="$SAVE_CFLAGS" fi ;; sparc*-*solaris*) # Find out which ABI we are using. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in yes*) LD="${LD-ld} -m elf64_sparc" ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" fi ;; esac ;; esac fi rm -rf conftest* ;; esac need_locks="$enable_libtool_lock" if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. set dummy ${ac_tool_prefix}mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$MANIFEST_TOOL"; then ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL if test -n "$MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 $as_echo "$MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_MANIFEST_TOOL"; then ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL # Extract the first word of "mt", so it can be a program name with args. set dummy mt; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_MANIFEST_TOOL"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL if test -n "$ac_ct_MANIFEST_TOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 $as_echo "$ac_ct_MANIFEST_TOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_MANIFEST_TOOL" = x; then MANIFEST_TOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL fi else MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" fi test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 $as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } if ${lt_cv_path_mainfest_tool+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_path_mainfest_tool=no echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out cat conftest.err >&5 if $GREP 'Manifest Tool' conftest.out > /dev/null; then lt_cv_path_mainfest_tool=yes fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 $as_echo "$lt_cv_path_mainfest_tool" >&6; } if test "x$lt_cv_path_mainfest_tool" != xyes; then MANIFEST_TOOL=: fi case $host_os in rhapsody* | darwin*) if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then ac_cv_prog_DSYMUTIL="$DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi DSYMUTIL=$ac_cv_prog_DSYMUTIL if test -n "$DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 $as_echo "$DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_DSYMUTIL"; then ac_ct_DSYMUTIL=$DSYMUTIL # Extract the first word of "dsymutil", so it can be a program name with args. set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL if test -n "$ac_ct_DSYMUTIL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 $as_echo "$ac_ct_DSYMUTIL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_DSYMUTIL" = x; then DSYMUTIL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac DSYMUTIL=$ac_ct_DSYMUTIL fi else DSYMUTIL="$ac_cv_prog_DSYMUTIL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then ac_cv_prog_NMEDIT="$NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi NMEDIT=$ac_cv_prog_NMEDIT if test -n "$NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 $as_echo "$NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_NMEDIT"; then ac_ct_NMEDIT=$NMEDIT # Extract the first word of "nmedit", so it can be a program name with args. set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT if test -n "$ac_ct_NMEDIT"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 $as_echo "$ac_ct_NMEDIT" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_NMEDIT" = x; then NMEDIT=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac NMEDIT=$ac_ct_NMEDIT fi else NMEDIT="$ac_cv_prog_NMEDIT" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then ac_cv_prog_LIPO="$LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi LIPO=$ac_cv_prog_LIPO if test -n "$LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 $as_echo "$LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_LIPO"; then ac_ct_LIPO=$LIPO # Extract the first word of "lipo", so it can be a program name with args. set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO if test -n "$ac_ct_LIPO"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 $as_echo "$ac_ct_LIPO" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_LIPO" = x; then LIPO=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac LIPO=$ac_ct_LIPO fi else LIPO="$ac_cv_prog_LIPO" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then ac_cv_prog_OTOOL="$OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL=$ac_cv_prog_OTOOL if test -n "$OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 $as_echo "$OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL"; then ac_ct_OTOOL=$OTOOL # Extract the first word of "otool", so it can be a program name with args. set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL if test -n "$ac_ct_OTOOL"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 $as_echo "$ac_ct_OTOOL" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL" = x; then OTOOL=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL=$ac_ct_OTOOL fi else OTOOL="$ac_cv_prog_OTOOL" fi if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then ac_cv_prog_OTOOL64="$OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi OTOOL64=$ac_cv_prog_OTOOL64 if test -n "$OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 $as_echo "$OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_prog_OTOOL64"; then ac_ct_OTOOL64=$OTOOL64 # Extract the first word of "otool64", so it can be a program name with args. set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 if test -n "$ac_ct_OTOOL64"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 $as_echo "$ac_ct_OTOOL64" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_ct_OTOOL64" = x; then OTOOL64=":" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac OTOOL64=$ac_ct_OTOOL64 fi else OTOOL64="$ac_cv_prog_OTOOL64" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no if test -z "${LT_MULTI_MODULE}"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the # link flags. rm -rf libconftest.dylib* echo "int foo(void){return 1;}" > conftest.c echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c" >&5 $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 fi rm -rf libconftest.dylib* rm -f conftest.* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no save_LDFLAGS=$LDFLAGS echo "_main" > conftest.sym LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_ld_exported_symbols_list=yes else lt_cv_ld_exported_symbols_list=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 $as_echo_n "checking for -force_load linker flag... " >&6; } if ${lt_cv_ld_force_load+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_force_load=no cat > conftest.c << _LT_EOF int forced_loaded() { return 2;} _LT_EOF echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 echo "$AR cru libconftest.a conftest.o" >&5 $AR cru libconftest.a conftest.o 2>&5 echo "$RANLIB libconftest.a" >&5 $RANLIB libconftest.a 2>&5 cat > conftest.c << _LT_EOF int main() { return 0;} _LT_EOF echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err _lt_result=$? if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then lt_cv_ld_force_load=yes else cat conftest.err >&5 fi rm -f conftest.err libconftest.a conftest conftest.c rm -rf conftest.dSYM fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 $as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; darwin1.*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; 10.[012]*) _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; 10.*) _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; esac ;; esac if test "$lt_cv_apple_cc_single_mod" = "yes"; then _lt_dar_single_mod='$single_module' fi if test "$lt_cv_ld_exported_symbols_list" = "yes"; then _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= fi ;; esac ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 $as_echo_n "checking how to run the C preprocessor... " >&6; } # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" do ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi done ac_cv_prog_CPP=$CPP fi CPP=$ac_cv_prog_CPP else ac_cv_prog_CPP=$CPP fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 $as_echo "$CPP" >&6; } ac_preproc_ok=false for ac_c_preproc_warn_flag in '' yes do # Use a header file that comes with gcc, so configuring glibc # with a fresh cross-compiler works. # Prefer to if __STDC__ is defined, since # exists even on freestanding compilers. # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. "Syntax error" is here to catch this case. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #ifdef __STDC__ # include #else # include #endif Syntax error _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : else # Broken: fails on valid input. continue fi rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if ac_fn_c_try_cpp "$LINENO"; then : # Broken: success on invalid input. continue else # Passes both tests. ac_preproc_ok=: break fi rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "C preprocessor \"$CPP\" fails sanity check See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include #include int main () { ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdc=yes else ac_cv_header_stdc=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "memchr" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "free" >/dev/null 2>&1; then : else ac_cv_header_stdc=no fi rm -f conftest* fi if test $ac_cv_header_stdc = yes; then # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if test "$cross_compiling" = yes; then : : else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #if ((' ' & 0x0FF) == 0x020) # define ISLOWER(c) ('a' <= (c) && (c) <= 'z') # define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) #else # define ISLOWER(c) \ (('a' <= (c) && (c) <= 'i') \ || ('j' <= (c) && (c) <= 'r') \ || ('s' <= (c) && (c) <= 'z')) # define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) #endif #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) int main () { int i; for (i = 0; i < 256; i++) if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) return 2; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : else ac_cv_header_stdc=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 $as_echo "$ac_cv_header_stdc" >&6; } if test $ac_cv_header_stdc = yes; then $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi # On IRIX 5.3, sys/types and inttypes.h are conflicting. for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ inttypes.h stdint.h unistd.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF fi done # Set options enable_dlopen=no enable_win32_dll=no # Check whether --enable-shared was given. if test "${enable_shared+set}" = set; then : enableval=$enable_shared; p=${PACKAGE-default} case $enableval in yes) enable_shared=yes ;; no) enable_shared=no ;; *) enable_shared=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_shared=yes fi done IFS="$lt_save_ifs" ;; esac else enable_shared=yes fi # Check whether --enable-static was given. if test "${enable_static+set}" = set; then : enableval=$enable_static; p=${PACKAGE-default} case $enableval in yes) enable_static=yes ;; no) enable_static=no ;; *) enable_static=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_static=yes fi done IFS="$lt_save_ifs" ;; esac else enable_static=yes fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : withval=$with_pic; pic_mode="$withval" else pic_mode=default fi test -z "$pic_mode" && pic_mode=default # Check whether --enable-fast-install was given. if test "${enable_fast_install+set}" = set; then : enableval=$enable_fast_install; p=${PACKAGE-default} case $enableval in yes) enable_fast_install=yes ;; no) enable_fast_install=no ;; *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," for pkg in $enableval; do IFS="$lt_save_ifs" if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done IFS="$lt_save_ifs" ;; esac else enable_fast_install=yes fi # This can be used to rebuild libtool when needed LIBTOOL_DEPS="$ltmain" # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' test -z "$LN_S" && LN_S="ln -s" if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null mkdir .libs 2>/dev/null if test -d .libs; then lt_cv_objdir=.libs else # MS-DOS does not allow filenames that begin with a dot. lt_cv_objdir=_libs fi rmdir .libs 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 $as_echo "$lt_cv_objdir" >&6; } objdir=$lt_cv_objdir cat >>confdefs.h <<_ACEOF #define LT_OBJDIR "$lt_cv_objdir/" _ACEOF case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac # Global variables: ofile=libtool can_build_shared=yes # All known linkers require a `.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" # Set sane defaults for various variables test -z "$CC" && CC=cc test -z "$LTCC" && LTCC=$CC test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o for cc_temp in $compiler""; do case $cc_temp in compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; \-*) ;; *) break;; esac done cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it test -z "$MAGIC_CMD" && MAGIC_CMD=file case $deplibs_check_method in file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/${ac_tool_prefix}file; then lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. ;; *) lt_save_MAGIC_CMD="$MAGIC_CMD" lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do IFS="$lt_save_ifs" test -z "$ac_dir" && ac_dir=. if test -f $ac_dir/file; then lt_cv_path_MAGIC_CMD="$ac_dir/file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : else cat <<_LT_EOF 1>&2 *** Warning: the command libtool uses to detect shared libraries, *** $file_magic_cmd, produces output that libtool cannot recognize. *** The result is that libtool may fail to recognize shared libraries *** as such. This will affect the creation of libtool libraries that *** depend on shared libraries, but programs linked with such libtool *** libraries will work regardless of this problem. Nevertheless, you *** may want to report the problem to your system manager and/or to *** bug-libtool@gnu.org _LT_EOF fi ;; esac fi break fi done IFS="$lt_save_ifs" MAGIC_CMD="$lt_save_MAGIC_CMD" ;; esac fi MAGIC_CMD="$lt_cv_path_MAGIC_CMD" if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi else MAGIC_CMD=: fi fi fi ;; esac # Use C for the default configuration in the libtool script lt_save_CC="$CC" ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # Source file extension for C test sources. ac_ext=c # Object file extension for compiled C test sources. objext=o objext=$objext # Code to be used in simple compile tests lt_simple_compile_test_code="int some_variable = 0;" # Code to be used in simple link tests lt_simple_link_test_code='int main(){return(0);}' # If no C compiler was specified, use CC. LTCC=${LTCC-"$CC"} # If no C compiler flags were specified, use CFLAGS. LTCFLAGS=${LTCFLAGS-"$CFLAGS"} # Allow CC to be a program name with arguments. compiler=$CC # Save the default compiler, since it gets overwritten when the other # tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. compiler_DEFAULT=$CC # save warnings/boilerplate of simple test code ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" >conftest.$ac_ext eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_compiler_boilerplate=`cat conftest.err` $RM conftest* ac_outfile=conftest.$ac_objext echo "$lt_simple_link_test_code" >conftest.$ac_ext eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change ## the running order or otherwise move them around unless you know exactly ## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then case $cc_basename in nvcc*) lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; *) lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-fno-rtti -fno-exceptions" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : fi fi lt_prog_compiler_wl= lt_prog_compiler_pic= lt_prog_compiler_static= if test "$GCC" = yes; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support lt_prog_compiler_pic='-fPIC' ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but # adding the `-m68020' flag to GCC prevents building anything better, # like `-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac ;; beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) # PIC is the default for these OSes. ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' ;; darwin* | rhapsody*) # PIC is the default on this platform # Common symbols not allowed in MH_DYLIB files lt_prog_compiler_pic='-fno-common' ;; haiku*) # PIC is the default for Haiku. # The "-static" flag exists, but is broken. lt_prog_compiler_static= ;; hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag # sets the default TLS model and affects inlining. case $host_cpu in hppa*64*) # +Z the default ;; *) lt_prog_compiler_pic='-fPIC' ;; esac ;; interix[3-9]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. ;; msdosdjgpp*) # Just because we use GCC doesn't mean we suddenly get shared libraries # on systems that don't support them. lt_prog_compiler_can_build_shared=no enable_shared=no ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; sysv4*MP*) if test -d /usr/nec; then lt_prog_compiler_pic=-Kconform_pic fi ;; *) lt_prog_compiler_pic='-fPIC' ;; esac case $cc_basename in nvcc*) # Cuda Compiler Driver 2.2 lt_prog_compiler_wl='-Xlinker ' lt_prog_compiler_pic='-Xcompiler -fPIC' ;; esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' if test "$host_cpu" = ia64; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' fi ;; mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' ;; hpux9* | hpux10* | hpux11*) lt_prog_compiler_wl='-Wl,' # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but # not for PA HP-UX. case $host_cpu in hppa*64*|ia64*) # +Z the default ;; *) lt_prog_compiler_pic='+Z' ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? lt_prog_compiler_static='${wl}-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) lt_prog_compiler_wl='-Wl,' # PIC (with -KPIC) is the default. lt_prog_compiler_static='-non_shared' ;; linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-static' ;; # icc used to be incompatible with GCC. # ICC 10 doesn't accept -KPIC any more. icc* | ifort*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fPIC' lt_prog_compiler_static='-static' ;; # Lahey Fortran 8.1. lf95*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; nagfor*) # NAG Fortran compiler lt_prog_compiler_wl='-Wl,-Wl,,' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' ;; ccc*) lt_prog_compiler_wl='-Wl,' # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; xl* | bgxl* | bgf* | mpixl*) # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in *Sun\ F* | *Sun*Fortran*) # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='' ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; esac ;; esac ;; newsos6) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; *nto* | *qnx*) # QNX uses GNU C++, but need to define -shared option too, otherwise # it will coredump. lt_prog_compiler_pic='-fPIC -shared' ;; osf3* | osf4* | osf5*) lt_prog_compiler_wl='-Wl,' # All OSF/1 code is PIC. lt_prog_compiler_static='-non_shared' ;; rdos*) lt_prog_compiler_static='-non_shared' ;; solaris*) lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; esac ;; sunos4*) lt_prog_compiler_wl='-Qoption ld ' lt_prog_compiler_pic='-PIC' lt_prog_compiler_static='-Bstatic' ;; sysv4 | sysv4.2uw2* | sysv4.3*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; sysv4*MP*) if test -d /usr/nec ;then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi ;; sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' ;; unicos*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_can_build_shared=no ;; uts4*) lt_prog_compiler_pic='-pic' lt_prog_compiler_static='-Bstatic' ;; *) lt_prog_compiler_can_build_shared=no ;; esac fi case $host_os in # For platforms which do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; *) lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 $as_echo_n "checking for $compiler option to produce PIC... " >&6; } if ${lt_cv_prog_compiler_pic+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic=$lt_prog_compiler_pic fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 $as_echo "$lt_cv_prog_compiler_pic" >&6; } lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. # if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="$lt_prog_compiler_pic -DPIC" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes fi fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } if test x"$lt_cv_prog_compiler_pic_works" = xyes; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; esac else lt_prog_compiler_pic= lt_prog_compiler_can_build_shared=no fi fi # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes fi else lt_cv_prog_compiler_static_works=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } if test x"$lt_cv_prog_compiler_static_works" = xyes; then : else lt_prog_compiler_static= fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no $RM -r conftest 2>/dev/null mkdir conftest cd conftest mkdir out echo "$lt_simple_compile_test_code" > conftest.$ac_ext lt_compiler_flag="-o out/conftest2.$ac_objext" # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes fi fi chmod u+w . 2>&5 $RM conftest* # SGI C++ compiler will create directory out/ii_files/ for # template instantiation test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files $RM out/* && rmdir out cd .. $RM -r conftest $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 $as_echo "$lt_cv_prog_compiler_c_o" >&6; } hard_links="nottested" if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } hard_links=yes $RM conftest* ln conftest.a conftest.b 2>/dev/null && hard_links=no touch conftest.a ln conftest.a conftest.b 2>&5 || hard_links=no ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } if test "$hard_links" = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 $as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} need_locks=warn fi else need_locks=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 $as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } runpath_var= allow_undefined_flag= always_export_symbols=no archive_cmds= archive_expsym_cmds= compiler_needs_object=no enable_shared_with_static_runtimes=no export_dynamic_flag_spec= export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' hardcode_automatic=no hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported inherit_rpath=no link_all_deplibs=unknown module_cmds= module_expsym_cmds= old_archive_from_new_cmds= old_archive_from_expsyms_cmds= thread_safe_flag_spec= whole_archive_flag_spec= # include_expsyms should be a list of space-separated symbols to be *always* # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude # it will be wrapped by ` (' and `)$', so one must not match beginning or # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', # as well as any symbol that contains `d'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if # the symbol is explicitly referenced. Since portable code cannot # rely on this symbol name, it's probably fine to never include it in # preloaded symbol tables. # Exclude shared library initialization/finalization symbols. extract_expsyms_cmds= case $host_os in cygwin* | mingw* | pw32* | cegcc*) # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. if test "$GCC" != yes; then with_gnu_ld=no fi ;; interix*) # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; openbsd*) with_gnu_ld=no ;; esac ld_shlibs=yes # On some targets, GNU ld is compatible enough with the native linker # that we're better off using the native interface for both. lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then case $host_os in aix*) # The AIX port of GNU ld has always aspired to compatibility # with the native linker. However, as the warning in the GNU ld # block says, versions before 2.19.5* couldn't really create working # shared libraries, regardless of the interface used. case `$LD -v 2>&1` in *\ \(GNU\ Binutils\)\ 2.19.5*) ;; *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; *\ \(GNU\ Binutils\)\ [3-9]*) ;; *) lt_use_gnu_ld_interface=yes ;; esac ;; *) lt_use_gnu_ld_interface=yes ;; esac fi if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' export_dynamic_flag_spec='${wl}--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no case `$LD -v 2>&1` in *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... *\ 2.11.*) ;; # other 2.11 versions *) supports_anon_versioning=yes ;; esac # See if GNU ld supports shared libraries. case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken if test "$host_cpu" != ia64; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you *** really care for shared libraries, you may want to install binutils *** 2.20 or above, or modify your PATH so that a non-GNU linker is found. *** You will then need to restart the configuration process. _LT_EOF fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; beos*) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' else ld_shlibs=no fi ;; cygwin* | mingw* | pw32* | cegcc*) # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' # If the export-symbols file already is a .def file (1st line # is EXPORTS), use it as is; otherwise, prepend... archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then cp $export_symbols $output_objdir/$soname.def; else echo EXPORTS > $output_objdir/$soname.def; cat $export_symbols >> $output_objdir/$soname.def; fi~ $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; haiku*) archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' link_all_deplibs=yes ;; interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ && test "$tmp_diet" = no then tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group f77 and f90 compilers whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 tmp_addflag=' -i_dynamic -nofor_main' ;; ifc* | ifort*) # Intel Fortran compiler tmp_addflag=' -nofor_main' ;; lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; nvcc*) # Cuda Compiler Driver 2.2 whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' fi case $cc_basename in xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac else ld_shlibs=no fi ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' fi ;; solaris*) if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: The releases 2.8.* of the GNU linker cannot reliably *** create shared libraries on Solaris systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.9.1 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) case `$LD -v 2>&1` in *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) ld_shlibs=no cat <<_LT_EOF 1>&2 *** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify *** your PATH or compiler configuration so that the native linker is *** used, and then restart. _LT_EOF ;; *) # For security reasons, it is highly recommended that you always # use absolute paths for naming shared libraries, and exclude the # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac ;; sunos4*) archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' wlarc= hardcode_direct=yes hardcode_shlibpath_var=no ;; *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac if test "$ld_shlibs" = no; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= whole_archive_flag_spec= fi else # PORTME fill in a description of your system's linker (not GNU ld) case $host_os in aix3*) allow_undefined_flag=unsupported always_export_symbols=yes archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported fi ;; aix[4-9]*) if test "$host_cpu" = ia64; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' no_entry_flag="" else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm # Also, AIX nm treats weak defined symbols like other global # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we # need to do runtime linking. case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then aix_use_runtimelinking=yes break fi done ;; esac exp_sym_flag='-bexport' no_entry_flag='-bnoentry' fi # When large executables or shared objects are built, AIX ld can # have problems creating the table of contents. If linking a library # or program results in "error TOC overflow" add -mminimal-toc to # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. archive_cmds='' hardcode_direct=yes hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes file_list_spec='${wl}-f,' if test "$GCC" = yes; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ collect2name=`${CC} -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then # We have reworked collect2 : else # We have old collect2 hardcode_direct=unsupported # It fails to find uninstalled libraries when the uninstalled # path is not listed in the libpath. Setting hardcode_minus_L # to unsupported forces relinking hardcode_minus_L=yes hardcode_libdir_flag_spec='-L$libdir' hardcode_libdir_separator= fi ;; esac shared_flag='-shared' if test "$aix_use_runtimelinking" = yes; then shared_flag="$shared_flag "'${wl}-G' fi else # not using gcc if test "$host_cpu" = ia64; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else if test "$aix_use_runtimelinking" = yes; then shared_flag='${wl}-G' else shared_flag='${wl}-bM:SRE' fi fi fi export_dynamic_flag_spec='${wl}-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes if test "$aix_use_runtimelinking" = yes; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. if test "${lt_cv_aix_libpath+set}" = set; then aix_libpath=$lt_cv_aix_libpath else if ${lt_cv_aix_libpath_+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_aix_libpath_sed=' /Import File Strings/,/^$/ { /^0/ { s/^0 *\([^ ]*\) *$/\1/ p } }' lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` # Check for a 64-bit object if we didn't find anything. if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test -z "$lt_cv_aix_libpath_"; then lt_cv_aix_libpath_="/usr/lib:/lib" fi fi aix_libpath=$lt_cv_aix_libpath_ fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' if test "$with_gnu_ld" = yes; then # We only use this code for GNU lds that support --whole-archive. whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' else # Exported symbols can be pulled into shared objects from archives whole_archive_flag_spec='$convenience' fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' fi fi ;; amigaos*) case $host_cpu in powerpc) # see comment about AmigaOS4 .so support archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes ;; esac ;; bsdi[45]*) export_dynamic_flag_spec=-rdynamic ;; cygwin* | mingw* | pw32* | cegcc*) # When not using gcc, we currently assume that we are using # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. case $cc_basename in cl*) # Native MSVC hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported always_export_symbols=yes file_list_spec='@' # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; else sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; fi~ $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ linknames=' # The linker will not automatically build a static lib if we build a DLL. # _LT_TAGVAR(old_archive_from_new_cmds, )='true' enable_shared_with_static_runtimes=yes export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' # Don't use ranlib old_postinstall_cmds='chmod 644 $oldlib' postlink_cmds='lt_outputfile="@OUTPUT@"~ lt_tool_outputfile="@TOOL_OUTPUT@"~ case $lt_outputfile in *.exe|*.EXE) ;; *) lt_outputfile="$lt_outputfile.exe" lt_tool_outputfile="$lt_tool_outputfile.exe" ;; esac~ if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; $RM "$lt_outputfile.manifest"; fi' ;; *) # Assume MSVC wrapper hardcode_libdir_flag_spec=' ' allow_undefined_flag=unsupported # Tell ltmain to make .lib files, not .a files. libext=lib # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' enable_shared_with_static_runtimes=yes ;; esac ;; darwin* | rhapsody*) archive_cmds_need_lc=no hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported if test "$lt_cv_ld_force_load" = "yes"; then whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' else whole_archive_flag_spec='' fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in ifort*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" else ld_shlibs=no fi ;; dgux*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; freebsd1*) ld_shlibs=no ;; # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little # extra space). freebsd2.2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. freebsd2*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) if test "$GCC" = yes; then archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' else archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' fi hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes export_dynamic_flag_spec='${wl}-E' ;; hpux10*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_flag_spec_ld='+b $libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes fi ;; hpux11*) if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) # Older versions of the 11.00 compiler do not understand -b yet # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 $as_echo_n "checking if $CC understands -b... " >&6; } if ${lt_cv_prog_compiler__b+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler__b=no save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -b" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then # The linker can only warn and ignore the option if not recognized # So say no if there are warnings if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler__b=yes fi else lt_cv_prog_compiler__b=yes fi fi $RM -r conftest* LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 $as_echo "$lt_cv_prog_compiler__b" >&6; } if test x"$lt_cv_prog_compiler__b" = xyes; then archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi ;; esac fi if test "$with_gnu_ld" = no; then hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' hardcode_libdir_separator=: case $host_cpu in hppa*64*|ia64*) hardcode_direct=no hardcode_shlibpath_var=no ;; *) hardcode_direct=yes hardcode_direct_absolute=yes export_dynamic_flag_spec='${wl}-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes ;; esac fi ;; irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. # This should be the same for all languages, so no per-tag cache variable. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 $as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } if ${lt_cv_irix_exported_symbol+:} false; then : $as_echo_n "(cached) " >&6 else save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : lt_cv_irix_exported_symbol=yes else lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 $as_echo "$lt_cv_irix_exported_symbol" >&6; } if test "$lt_cv_irix_exported_symbol" = yes; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF fi hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; *nto* | *qnx*) ;; openbsd*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' export_dynamic_flag_spec='${wl}-E' else case $host_os in openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-R$libdir' ;; *) archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='${wl}-rpath,$libdir' ;; esac fi else ld_shlibs=no fi ;; os2*) hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' fi archive_cmds_need_lc='no' hardcode_libdir_separator=: ;; solaris*) no_undefined_flag=' -z defs' if test "$GCC" = yes; then wlarc='${wl}' archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) wlarc='${wl}' archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi hardcode_libdir_flag_spec='-R$libdir' hardcode_shlibpath_var=no case $host_os in solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, # but understands `-z linker_flag'. GCC discards it without `$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) if test "$GCC" = yes; then whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi ;; esac link_all_deplibs=yes ;; sunos4*) if test "x$host_vendor" = xsequent; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi hardcode_libdir_flag_spec='-L$libdir' hardcode_direct=yes hardcode_minus_L=yes hardcode_shlibpath_var=no ;; sysv4) case $host_vendor in sni) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes # is this really true??? ;; siemens) ## LD is ld it makes a PLAMLIB ## CC just makes a GrossModule. archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' reload_cmds='$CC -r -o $output$reload_objs' hardcode_direct=no ;; motorola) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=no #Motorola manual says yes, but my tests say they lie ;; esac runpath_var='LD_RUN_PATH' hardcode_shlibpath_var=no ;; sysv4.3*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no export_dynamic_flag_spec='-Bexport' ;; sysv4*MP*) if test -d /usr/nec; then archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_shlibpath_var=no runpath_var=LD_RUN_PATH hardcode_runpath_var=yes ld_shlibs=yes fi ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) no_undefined_flag='${wl}-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) # Note: We can NOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. no_undefined_flag='${wl}-z,text' allow_undefined_flag='${wl}-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no hardcode_libdir_flag_spec='${wl}-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes export_dynamic_flag_spec='${wl}-Bexport' runpath_var='LD_RUN_PATH' if test "$GCC" = yes; then archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; uts4*) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_libdir_flag_spec='-L$libdir' hardcode_shlibpath_var=no ;; *) ld_shlibs=no ;; esac if test x$host_vendor = xsni; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) export_dynamic_flag_spec='${wl}-Blargedynsym' ;; esac fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } test "$ld_shlibs" = no && can_build_shared=no with_gnu_ld=$with_gnu_ld # # Do we need to explicitly link libc? # case "x$archive_cmds_need_lc" in x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes if test "$enable_shared" = yes && test "$GCC" = yes; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. ;; '$CC '*) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } if ${lt_cv_archive_cmds_need_lc+:} false; then : $as_echo_n "(cached) " >&6 else $RM conftest* echo "$lt_simple_compile_test_code" > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then soname=conftest lib=conftest libobjs=conftest.$ac_objext deplibs= wl=$lt_prog_compiler_wl pic_flag=$lt_prog_compiler_pic compiler_flags=-v linker_flags=-v verstring= output_objdir=. libname=conftest lt_save_allow_undefined_flag=$allow_undefined_flag allow_undefined_flag= if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } then lt_cv_archive_cmds_need_lc=no else lt_cv_archive_cmds_need_lc=yes fi allow_undefined_flag=$lt_save_allow_undefined_flag else cat conftest.err 1>&5 fi $RM conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 $as_echo "$lt_cv_archive_cmds_need_lc" >&6; } archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } if test "$GCC" = yes; then case $host_os in darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac case $host_os in mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; *) lt_sed_strip_eq="s,=/,/,g" ;; esac lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` case $lt_search_path_spec in *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` ;; *) lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` ;; esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` for lt_sys_path in $lt_search_path_spec; do if test -d "$lt_sys_path/$lt_multi_os_dir"; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" else test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { lt_foo="/" $lt_i lt_foo; } else { lt_count--; } } } } if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` # AWK program above erroneously prepends '/' to C:/dos/paths # for these hosts. case $host_os in mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ $SED 's,/\([A-Za-z]:\),\1,g'` ;; esac sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= shrext_cmds=".so" postinstall_cmds= postuninstall_cmds= finish_cmds= finish_eval= shlibpath_var= shlibpath_overrides_runpath=unknown version_type=none dynamic_linker="$host_os ld.so" sys_lib_dlsearch_path_spec="/lib /usr/lib" need_lib_prefix=unknown hardcode_into_libs=no # when you set need_version to no, make sure it does not cause -set_version # flags to be left without arguments need_version=unknown case $host_os in aix3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. soname_spec='${libname}${release}${shared_ext}$major' ;; aix[4-9]*) version_type=linux need_lib_prefix=no need_version=no hardcode_into_libs=yes if test "$host_cpu" = ia64; then # AIX 5 supports IA64 library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with # the line `#! .'. This would cause the generated library to # depend on `.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac # AIX (on Power*) has no versioning support, so currently we can not hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. if test "$aix_use_runtimelinking" = yes; then # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' else # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. library_names_spec='${libname}${release}.a $libname.a' soname_spec='${libname}${release}${shared_ext}$major' fi shlibpath_var=LIBPATH fi ;; amigaos*) case $host_cpu in powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) library_names_spec='${libname}${shared_ext}' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) version_type=linux need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" # the default ld.so.conf also contains /usr/contrib/lib and # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow # libtool to hard-code these into programs ;; cygwin* | mingw* | pw32* | cegcc*) version_type=windows shrext_cmds=".dll" need_version=no need_lib_prefix=no case $GCC,$cc_basename in yes,*) # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ chmod a+x \$dldir/$dlname~ if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; fi' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' ;; esac dynamic_linker='Win32 ld.exe' ;; *,cl*) # Native MSVC libname_spec='$name' soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' library_names_spec='${libname}.dll.lib' case $build_os in mingw*) sys_lib_search_path_spec= lt_save_ifs=$IFS IFS=';' for lt_path in $LIB do IFS=$lt_save_ifs # Let DOS variable expansion print the short 8.3 style file name. lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" done IFS=$lt_save_ifs # Convert to MSYS style. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` ;; cygwin*) # Convert to unix form, then to dos form, then back to unix form # but this time dos style (no spaces!) so that the unix form looks # like /cygdrive/c/PROGRA~1:/cygdr... sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` ;; *) sys_lib_search_path_spec="$LIB" if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then # It is most probably a Windows format PATH. sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` else sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` fi # FIXME: find the short name or the path components, as spaces are # common. (e.g. "Program Files" -> "PROGRA~1") ;; esac # DLL is installed to $(libdir)/../bin by postinstall_cmds postinstall_cmds='base_file=`basename \${file}`~ dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname' postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ dlpath=$dir/\$dldll~ $RM \$dlpath' shlibpath_overrides_runpath=yes dynamic_linker='Win32 link.exe' ;; *) # Assume MSVC wrapper library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' dynamic_linker='Win32 ld.exe' ;; esac # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; darwin* | rhapsody*) dynamic_linker="$host_os dyld" version_type=darwin need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' soname_spec='${libname}${release}${major}$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' ;; dgux*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; freebsd1*) dynamic_linker=no ;; freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. if test -x /usr/bin/objformat; then objformat=`/usr/bin/objformat` else case $host_os in freebsd[123]*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' need_version=no need_lib_prefix=no ;; freebsd-*) library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in freebsd2*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; *) # from 4.6 on, and DragonFly shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; esac ;; gnu*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH hardcode_into_libs=yes ;; haiku*) version_type=linux need_lib_prefix=no need_version=no dynamic_linker="$host_os runtime_loader" library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LIBRARY_PATH shlibpath_overrides_runpath=yes sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. version_type=sunos need_lib_prefix=no need_version=no case $host_cpu in ia64*) shrext_cmds='.so' hardcode_into_libs=yes dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' if test "X$HPUX_IA64_MODE" = X32; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" fi sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' hardcode_into_libs=yes dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; *) shrext_cmds='.sl' dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' ;; esac # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' # or fails outright, so override atomically: install_override_mode=555 ;; interix[3-9]*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) if test "$lt_cv_prog_gnu_ld" = yes; then version_type=linux else version_type=irix fi ;; esac need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= ;; *) case $LD in # libtool.m4 will add one of these switches to LD *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= libmagic=32-bit;; *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 libmagic=64-bit;; *) libsuff= shlibsuff= libmagic=never-match;; esac ;; esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" hardcode_into_libs=yes ;; # No shared lib support for Linux oldld, aout, or coff. linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; # This must be Linux ELF. linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no # Some binutils ld are patched to set DT_RUNPATH if ${lt_cv_shlibpath_overrides_runpath+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_shlibpath_overrides_runpath=no save_LDFLAGS=$LDFLAGS save_libdir=$libdir eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int main () { ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS=$save_LDFLAGS libdir=$save_libdir fi shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi # We used to test for /lib/ld.so.1 and disable shared libraries on # powerpc, because MkLinux only supported shared libraries with the # GNU dynamic linker. Since this was broken with cross compilers, # most powerpc-linux boxes support dynamic linking these days and # people can always --disable-shared, the test was removed, and we # assume the GNU/Linux dynamic linker is in use. dynamic_linker='GNU/Linux ld.so' ;; netbsd*) version_type=sunos need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes ;; newsos6) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; *nto* | *qnx*) version_type=qnx need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; openbsd*) version_type=sunos sys_lib_dlsearch_path_spec="/usr/lib" need_lib_prefix=no # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. case $host_os in openbsd3.3 | openbsd3.3.*) need_version=yes ;; *) need_version=no ;; esac library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then case $host_os in openbsd2.[89] | openbsd2.[89].*) shlibpath_overrides_runpath=no ;; *) shlibpath_overrides_runpath=yes ;; esac else shlibpath_overrides_runpath=yes fi ;; os2*) libname_spec='$name' shrext_cmds=".dll" need_lib_prefix=no library_names_spec='$libname${shared_ext} $libname.a' dynamic_linker='OS/2 ld.exe' shlibpath_var=LIBPATH ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no soname_spec='${libname}${release}${shared_ext}$major' library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" ;; rdos*) dynamic_linker=no ;; solaris*) version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes # ldd complains unless libraries are executable postinstall_cmds='chmod +x $lib' ;; sunos4*) version_type=sunos library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes if test "$with_gnu_ld" = yes; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) shlibpath_overrides_runpath=no need_lib_prefix=no runpath_var=LD_RUN_PATH ;; siemens) need_lib_prefix=no ;; motorola) need_lib_prefix=no need_version=no shlibpath_overrides_runpath=no sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' ;; esac ;; sysv4*MP*) if test -d /usr/nec ;then version_type=linux library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' soname_spec='$libname${shared_ext}.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) version_type=freebsd-elf need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes if test "$with_gnu_ld" = yes; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' case $host_os in sco3.2v5*) sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" ;; esac fi sys_lib_dlsearch_path_spec='/usr/lib' ;; tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. version_type=linux need_lib_prefix=no need_version=no library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) version_type=linux library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' soname_spec='${libname}${release}${shared_ext}$major' shlibpath_var=LD_LIBRARY_PATH ;; *) dynamic_linker=no ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } test "$dynamic_linker" = no && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" if test "$GCC" = yes; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" fi if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || test "X$hardcode_automatic" = "Xyes" ; then # We can hardcode non-existent directories. if test "$hardcode_direct" != no && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && test "$hardcode_minus_L" != no; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else # We can link without hardcoding, and we can hardcode nonexisting dirs. hardcode_action=immediate fi else # We cannot hardcode anything, or else we can only hardcode existing # directories. hardcode_action=unsupported fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } if test "$hardcode_action" = relink || test "$inherit_rpath" = yes; then # Fast installation is not supported enable_fast_install=no elif test "$shlibpath_overrides_runpath" = yes || test "$enable_shared" = no; then # Fast installation is not necessary enable_fast_install=needless fi if test "x$enable_dlopen" != xyes; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown else lt_cv_dlopen=no lt_cv_dlopen_libs= case $host_os in beos*) lt_cv_dlopen="load_add_on" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) lt_cv_dlopen="LoadLibrary" lt_cv_dlopen_libs= ;; cygwin*) lt_cv_dlopen="dlopen" lt_cv_dlopen_libs= ;; darwin*) # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else lt_cv_dlopen="dyld" lt_cv_dlopen_libs= lt_cv_dlopen_self=yes fi ;; *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" if test "x$ac_cv_func_shl_load" = xyes; then : lt_cv_dlopen="shl_load" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char shl_load (); int main () { return shl_load (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_shl_load=yes else ac_cv_lib_dld_shl_load=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } if test "x$ac_cv_lib_dld_shl_load" = xyes; then : lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" if test "x$ac_cv_func_dlopen" = xyes; then : lt_cv_dlopen="dlopen" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldl $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dl_dlopen=yes else ac_cv_lib_dl_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } if test "x$ac_cv_lib_dl_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lsvld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_svld_dlopen=yes else ac_cv_lib_svld_dlopen=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } if test "x$ac_cv_lib_svld_dlopen" = xyes; then : lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldld $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dld_link (); int main () { return dld_link (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_dld_dld_link=yes else ac_cv_lib_dld_dld_link=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } if test "x$ac_cv_lib_dld_dld_link" = xyes; then : lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" fi fi fi fi fi fi ;; esac if test "x$lt_cv_dlopen" != xno; then enable_dlopen=yes else enable_dlopen=no fi case $lt_cv_dlopen in dlopen) save_CPPFLAGS="$CPPFLAGS" test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" save_LDFLAGS="$LDFLAGS" wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" save_LIBS="$LIBS" LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; esac else : # compilation failed lt_cv_dlopen_self=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } if test "x$lt_cv_dlopen_self" = xyes; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include #endif #include #ifdef RTLD_GLOBAL # define LT_DLGLOBAL RTLD_GLOBAL #else # ifdef DL_GLOBAL # define LT_DLGLOBAL DL_GLOBAL # else # define LT_DLGLOBAL 0 # endif #endif /* We may have to define LT_DLLAZY_OR_NOW in the command line if we find out it does not work in some platform. */ #ifndef LT_DLLAZY_OR_NOW # ifdef RTLD_LAZY # define LT_DLLAZY_OR_NOW RTLD_LAZY # else # ifdef DL_LAZY # define LT_DLLAZY_OR_NOW DL_LAZY # else # ifdef RTLD_NOW # define LT_DLLAZY_OR_NOW RTLD_NOW # else # ifdef DL_NOW # define LT_DLLAZY_OR_NOW DL_NOW # else # define LT_DLLAZY_OR_NOW 0 # endif # endif # endif # endif #endif /* When -fvisbility=hidden is used, assume the code has been annotated correspondingly for the symbols needed. */ #if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) int fnord () __attribute__((visibility("default"))); #endif int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); int status = $lt_dlunknown; if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; else { if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; else puts (dlerror ()); } /* dlclose (self); */ } else puts (dlerror ()); return status; } _LT_EOF if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; esac else : # compilation failed lt_cv_dlopen_self_static=no fi fi rm -fr conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 $as_echo "$lt_cv_dlopen_self_static" >&6; } fi CPPFLAGS="$save_CPPFLAGS" LDFLAGS="$save_LDFLAGS" LIBS="$save_LIBS" ;; esac case $lt_cv_dlopen_self in yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; *) enable_dlopen_self=unknown ;; esac case $lt_cv_dlopen_self_static in yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; *) enable_dlopen_self_static=unknown ;; esac fi striplib= old_striplib= { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 $as_echo_n "checking whether stripping libraries is possible... " >&6; } if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" test -z "$striplib" && striplib="$STRIP --strip-unneeded" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) if test -n "$STRIP" ; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ;; esac fi # Report which library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } test "$can_build_shared" = "no" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) test "$enable_shared" = yes && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' fi ;; aix[4-9]*) if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then test "$enable_shared" = yes && enable_static=no fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. test "$enable_shared" = yes || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu CC="$lt_save_CC" ac_config_commands="$ac_config_commands libtool" # Only expand once: if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi PKG_CONFIG=$ac_cv_path_PKG_CONFIG if test -n "$PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 $as_echo "$PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test -z "$ac_cv_path_PKG_CONFIG"; then ac_pt_PKG_CONFIG=$PKG_CONFIG # Extract the first word of "pkg-config", so it can be a program name with args. set dummy pkg-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : $as_echo_n "(cached) " >&6 else case $ac_pt_PKG_CONFIG in [\\/]* | ?:[\\/]*) ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG if test -n "$ac_pt_PKG_CONFIG"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 $as_echo "$ac_pt_PKG_CONFIG" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test "x$ac_pt_PKG_CONFIG" = x; then PKG_CONFIG="" else case $cross_compiling:$ac_tool_warned in yes:) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 $as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} ac_tool_warned=yes ;; esac PKG_CONFIG=$ac_pt_PKG_CONFIG fi else PKG_CONFIG="$ac_cv_path_PKG_CONFIG" fi fi if test -n "$PKG_CONFIG"; then _pkg_min_version=0.9.0 { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 $as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } PKG_CONFIG="" fi fi # # Check for how to compile threaded stuff # ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS" >&5 $as_echo_n "checking for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char pthread_join (); int main () { return pthread_join (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 $as_echo "$ax_pthread_ok" >&6; } if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case ${host_os} in solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac # Clang doesn't consider unrecognized options an error unless we specify # -Werror. We throw in some extra Clang-specific options to ensure that # this doesn't happen for GCC, which also accepts -Werror. { $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler needs -Werror to reject unknown flags" >&5 $as_echo_n "checking if compiler needs -Werror to reject unknown flags... " >&6; } save_CFLAGS="$CFLAGS" ax_pthread_extra_flags="-Werror" CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int foo(void); int main () { foo() ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else ax_pthread_extra_flags= { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CFLAGS="$save_CFLAGS" if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work without any flags" >&5 $as_echo_n "checking whether pthreads work without any flags... " >&6; } ;; -*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthreads work with $flag" >&5 $as_echo_n "checking whether pthreads work with $flag... " >&6; } PTHREAD_CFLAGS="$flag" ;; pthread-config) # Extract the first word of "pthread-config", so it can be a program name with args. set dummy pthread-config; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_ax_pthread_config+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ax_pthread_config"; then ac_cv_prog_ax_pthread_config="$ax_pthread_config" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ax_pthread_config="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_prog_ax_pthread_config" && ac_cv_prog_ax_pthread_config="no" fi fi ax_pthread_config=$ac_cv_prog_ax_pthread_config if test -n "$ax_pthread_config"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_config" >&5 $as_echo "$ax_pthread_config" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the pthreads library -l$flag" >&5 $as_echo_n "checking for the pthreads library -l$flag... " >&6; } PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; } int main () { pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_pthread_ok=yes fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_pthread_ok" >&5 $as_echo "$ax_pthread_ok" >&6; } if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for joinable pthread attribute" >&5 $as_echo_n "checking for joinable pthread attribute... " >&6; } attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int attr = $attr; return attr /* ; */ ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : attr_name=$attr; break fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext done { $as_echo "$as_me:${as_lineno-$LINENO}: result: $attr_name" >&5 $as_echo "$attr_name" >&6; } if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then cat >>confdefs.h <<_ACEOF #define PTHREAD_CREATE_JOINABLE $attr_name _ACEOF fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if more special flags are required for pthreads" >&5 $as_echo_n "checking if more special flags are required for pthreads... " >&6; } flag=no case ${host_os} in aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; osf* | hpux*) flag="-D_REENTRANT";; solaris*) if test "$GCC" = "yes"; then flag="-D_REENTRANT" else # TODO: What about Clang on Solaris? flag="-mt -D_REENTRANT" fi ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $flag" >&5 $as_echo "$flag" >&6; } if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for PTHREAD_PRIO_INHERIT" >&5 $as_echo_n "checking for PTHREAD_PRIO_INHERIT... " >&6; } if ${ax_cv_PTHREAD_PRIO_INHERIT+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { int i = PTHREAD_PRIO_INHERIT; ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ax_cv_PTHREAD_PRIO_INHERIT=yes else ax_cv_PTHREAD_PRIO_INHERIT=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_PTHREAD_PRIO_INHERIT" >&5 $as_echo "$ax_cv_PTHREAD_PRIO_INHERIT" >&6; } if test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"; then : $as_echo "#define HAVE_PTHREAD_PRIO_INHERIT 1" >>confdefs.h fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: compile with *_r variant if test "x$GCC" != xyes; then case $host_os in aix*) case "x/$CC" in #( x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6) : #handle absolute path differently from PATH based program lookup case "x$CC" in #( x/*) : if as_fn_executable_p ${CC}_r; then : PTHREAD_CC="${CC}_r" fi ;; #( *) : for ac_prog in ${CC}_r do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_PTHREAD_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$PTHREAD_CC"; then ac_cv_prog_PTHREAD_CC="$PTHREAD_CC" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_PTHREAD_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi PTHREAD_CC=$ac_cv_prog_PTHREAD_CC if test -n "$PTHREAD_CC"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PTHREAD_CC" >&5 $as_echo "$PTHREAD_CC" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi test -n "$PTHREAD_CC" && break done test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" ;; esac ;; #( *) : ;; esac ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then $as_echo "#define HAVE_PTHREAD 1" >>confdefs.h : else ax_pthread_ok=no fi ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu # # save outer values # outer_CFLAGS="$CFLAGS" outer_CPPFLAGS="$CPPFLAGS" outer_LDFLAGS="$LDFLAGS" outer_LIBS="$LIBS" # # Checks for libraries # saved_LIBS="$LIBS" LIBS="" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_addr" >&5 $as_echo_n "checking for library containing inet_addr... " >&6; } if ${ac_cv_search_inet_addr+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_addr (); int main () { return inet_addr (); ; return 0; } _ACEOF for ac_lib in '' nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_inet_addr=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_inet_addr+:} false; then : break fi done if ${ac_cv_search_inet_addr+:} false; then : else ac_cv_search_inet_addr=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_addr" >&5 $as_echo "$ac_cv_search_inet_addr" >&6; } ac_res=$ac_cv_search_inet_addr if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi LIBNSL_LIBS="$LIBS" LIBS="$saved_LIBS" saved_LIBS="$LIBS" LIBS="" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi LIBDL_LIBS="$LIBS" LIBS="$saved_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5 $as_echo_n "checking for library containing socket... " >&6; } if ${ac_cv_search_socket+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char socket (); int main () { return socket (); ; return 0; } _ACEOF for ac_lib in '' socket; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_socket=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_socket+:} false; then : break fi done if ${ac_cv_search_socket+:} false; then : else ac_cv_search_socket=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5 $as_echo "$ac_cv_search_socket" >&6; } ac_res=$ac_cv_search_socket if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_aton" >&5 $as_echo_n "checking for library containing inet_aton... " >&6; } if ${ac_cv_search_inet_aton+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_aton (); int main () { return inet_aton (); ; return 0; } _ACEOF for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_inet_aton=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_inet_aton+:} false; then : break fi done if ${ac_cv_search_inet_aton+:} false; then : else ac_cv_search_inet_aton=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_aton" >&5 $as_echo "$ac_cv_search_inet_aton" >&6; } ac_res=$ac_cv_search_inet_aton if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_pton" >&5 $as_echo_n "checking for library containing inet_pton... " >&6; } if ${ac_cv_search_inet_pton+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_pton (); int main () { return inet_pton (); ; return 0; } _ACEOF for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_inet_pton=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_inet_pton+:} false; then : break fi done if ${ac_cv_search_inet_pton+:} false; then : else ac_cv_search_inet_pton=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_pton" >&5 $as_echo "$ac_cv_search_inet_pton" >&6; } ac_res=$ac_cv_search_inet_pton if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_INET_PTON 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing inet_ntop" >&5 $as_echo_n "checking for library containing inet_ntop... " >&6; } if ${ac_cv_search_inet_ntop+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char inet_ntop (); int main () { return inet_ntop (); ; return 0; } _ACEOF for ac_lib in '' resolv nsl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_inet_ntop=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_inet_ntop+:} false; then : break fi done if ${ac_cv_search_inet_ntop+:} false; then : else ac_cv_search_inet_ntop=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_inet_ntop" >&5 $as_echo "$ac_cv_search_inet_ntop" >&6; } ac_res=$ac_cv_search_inet_ntop if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_INET_NTOP 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getaddrinfo" >&5 $as_echo_n "checking for library containing getaddrinfo... " >&6; } if ${ac_cv_search_getaddrinfo+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getaddrinfo (); int main () { return getaddrinfo (); ; return 0; } _ACEOF for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_getaddrinfo=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_getaddrinfo+:} false; then : break fi done if ${ac_cv_search_getaddrinfo+:} false; then : else ac_cv_search_getaddrinfo=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getaddrinfo" >&5 $as_echo "$ac_cv_search_getaddrinfo" >&6; } ac_res=$ac_cv_search_getaddrinfo if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing res_ninit" >&5 $as_echo_n "checking for library containing res_ninit... " >&6; } if ${ac_cv_search_res_ninit+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char res_ninit (); int main () { return res_ninit (); ; return 0; } _ACEOF for ac_lib in '' resolv; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_res_ninit=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_res_ninit+:} false; then : break fi done if ${ac_cv_search_res_ninit+:} false; then : else ac_cv_search_res_ninit=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_ninit" >&5 $as_echo "$ac_cv_search_res_ninit" >&6; } ac_res=$ac_cv_search_res_ninit if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_RES_NINIT 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing res_sertservers" >&5 $as_echo_n "checking for library containing res_sertservers... " >&6; } if ${ac_cv_search_res_sertservers+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char res_sertservers (); int main () { return res_sertservers (); ; return 0; } _ACEOF for ac_lib in '' resolv bind; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_res_sertservers=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_res_sertservers+:} false; then : break fi done if ${ac_cv_search_res_sertservers+:} false; then : else ac_cv_search_res_sertservers=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_res_sertservers" >&5 $as_echo "$ac_cv_search_res_sertservers" >&6; } ac_res=$ac_cv_search_res_sertservers if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_RES_SETSERVERS 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getopt_long" >&5 $as_echo_n "checking for library containing getopt_long... " >&6; } if ${ac_cv_search_getopt_long+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getopt_long (); int main () { return getopt_long (); ; return 0; } _ACEOF for ac_lib in '' iberty; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_getopt_long=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_getopt_long+:} false; then : break fi done if ${ac_cv_search_getopt_long+:} false; then : else ac_cv_search_getopt_long=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getopt_long" >&5 $as_echo "$ac_cv_search_getopt_long" >&6; } ac_res=$ac_cv_search_getopt_long if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_GETOPT_LONG 1" >>confdefs.h fi for ac_header in sys/types.h netinet/in.h arpa/nameser.h netdb.h resolv.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "#ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_NETINET_IN_H # include /* inet_ functions / structs */ #endif #ifdef HAVE_ARPA_NAMESER_H # include /* DNS HEADER struct */ #endif #ifdef HAVE_NETDB_H # include #endif " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # # Check for types # ac_fn_c_check_type "$LINENO" "useconds_t" "ac_cv_type_useconds_t" "$ac_includes_default" if test "x$ac_cv_type_useconds_t" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_USECONDS_T 1 _ACEOF fi # # See if libopendkim will need -lresolv # dnscheck=' #include "confdefs.h" #include #include #include #include int main() { res_mkquery (0, 0, 0, 0, 0, 0, 0, 0, 0); dn_expand (0, 0, 0, 0, 0); dn_skipname (0, 0); dn_comp (0, 0, 0, 0, 0); return 0; }' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the resolver works without -lresolv" >&5 $as_echo_n "checking whether the resolver works without -lresolv... " >&6; } LIBRESOLV= cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $dnscheck _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the resolver works with -lresolv" >&5 $as_echo_n "checking whether the resolver works with -lresolv... " >&6; } saved_LIBS="$LIBS" LIBS="$outer_LIBS -lresolv" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $dnscheck _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } LIBRESOLV=-lresolv else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } as_fn_error $? "need workable resolver library" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS="$saved_LIBS" fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext # # Checks for header files # for ac_header in arpa/inet.h fcntl.h limits.h iso/limits_iso.h netdb.h netinet/in.h paths.h stdlib.h string.h sys/file.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h stdint.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done # # Checks for typedefs, structures, and compiler characteristics. # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdbool.h that conforms to C99" >&5 $as_echo_n "checking for stdbool.h that conforms to C99... " >&6; } if ${ac_cv_header_stdbool_h+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #ifndef bool "error: bool is not defined" #endif #ifndef false "error: false is not defined" #endif #if false "error: false is not 0" #endif #ifndef true "error: true is not defined" #endif #if true != 1 "error: true is not 1" #endif #ifndef __bool_true_false_are_defined "error: __bool_true_false_are_defined is not defined" #endif struct s { _Bool s: 1; _Bool t; } s; char a[true == 1 ? 1 : -1]; char b[false == 0 ? 1 : -1]; char c[__bool_true_false_are_defined == 1 ? 1 : -1]; char d[(bool) 0.5 == true ? 1 : -1]; /* See body of main program for 'e'. */ char f[(_Bool) 0.0 == false ? 1 : -1]; char g[true]; char h[sizeof (_Bool)]; char i[sizeof s.t]; enum { j = false, k = true, l = false * true, m = true * 256 }; /* The following fails for HP aC++/ANSI C B3910B A.05.55 [Dec 04 2003]. */ _Bool n[m]; char o[sizeof n == m * sizeof n[0] ? 1 : -1]; char p[-1 - (_Bool) 0 < 0 && -1 - (bool) 0 < 0 ? 1 : -1]; /* Catch a bug in an HP-UX C compiler. See http://gcc.gnu.org/ml/gcc-patches/2003-12/msg02303.html http://lists.gnu.org/archive/html/bug-coreutils/2005-11/msg00161.html */ _Bool q = true; _Bool *pq = &q; int main () { bool e = &s; *pq |= q; *pq |= ! q; /* Refer to every declared value, to avoid compiler optimizations. */ return (!a + !b + !c + !d + !e + !f + !g + !h + !i + !!j + !k + !!l + !m + !n + !o + !p + !q + !pq); ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_stdbool_h=yes else ac_cv_header_stdbool_h=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdbool_h" >&5 $as_echo "$ac_cv_header_stdbool_h" >&6; } ac_fn_c_check_type "$LINENO" "_Bool" "ac_cv_type__Bool" "$ac_includes_default" if test "x$ac_cv_type__Bool" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE__BOOL 1 _ACEOF fi if test $ac_cv_header_stdbool_h = yes; then $as_echo "#define HAVE_STDBOOL_H 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uid_t in sys/types.h" >&5 $as_echo_n "checking for uid_t in sys/types.h... " >&6; } if ${ac_cv_type_uid_t+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "uid_t" >/dev/null 2>&1; then : ac_cv_type_uid_t=yes else ac_cv_type_uid_t=no fi rm -f conftest* fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_uid_t" >&5 $as_echo "$ac_cv_type_uid_t" >&6; } if test $ac_cv_type_uid_t = no; then $as_echo "#define uid_t int" >>confdefs.h $as_echo "#define gid_t int" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" if test "x$ac_cv_type_mode_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define mode_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$ac_includes_default" if test "x$ac_cv_type_off_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define off_t long int _ACEOF fi ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$ac_includes_default" if test "x$ac_cv_type_pid_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define pid_t int _ACEOF fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" if test "x$ac_cv_type_size_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define size_t unsigned int _ACEOF fi ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default" if test "x$ac_cv_type_ssize_t" = xyes; then : else cat >>confdefs.h <<_ACEOF #define ssize_t int _ACEOF fi ac_fn_c_find_uintX_t "$LINENO" "16" "ac_cv_c_uint16_t" case $ac_cv_c_uint16_t in #( no|yes) ;; #( *) cat >>confdefs.h <<_ACEOF #define uint16_t $ac_cv_c_uint16_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "32" "ac_cv_c_uint32_t" case $ac_cv_c_uint32_t in #( no|yes) ;; #( *) $as_echo "#define _UINT32_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint32_t $ac_cv_c_uint32_t _ACEOF ;; esac ac_fn_c_find_uintX_t "$LINENO" "64" "ac_cv_c_uint64_t" case $ac_cv_c_uint64_t in #( no|yes) ;; #( *) $as_echo "#define _UINT64_T 1" >>confdefs.h cat >>confdefs.h <<_ACEOF #define uint64_t $ac_cv_c_uint64_t _ACEOF ;; esac # # Checks for library functions. # for ac_header in vfork.h do : ac_fn_c_check_header_mongrel "$LINENO" "vfork.h" "ac_cv_header_vfork_h" "$ac_includes_default" if test "x$ac_cv_header_vfork_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_VFORK_H 1 _ACEOF fi done for ac_func in fork vfork do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done if test "x$ac_cv_func_fork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working fork" >&5 $as_echo_n "checking for working fork... " >&6; } if ${ac_cv_func_fork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_fork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* By Ruediger Kuhlmann. */ return fork () < 0; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_fork_works=yes else ac_cv_func_fork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_fork_works" >&5 $as_echo "$ac_cv_func_fork_works" >&6; } else ac_cv_func_fork_works=$ac_cv_func_fork fi if test "x$ac_cv_func_fork_works" = xcross; then case $host in *-*-amigaos* | *-*-msdosdjgpp*) # Override, as these systems have only a dummy fork() stub ac_cv_func_fork_works=no ;; *) ac_cv_func_fork_works=yes ;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_fork_works guessed because of cross compilation" >&2;} fi ac_cv_func_vfork_works=$ac_cv_func_vfork if test "x$ac_cv_func_vfork" = xyes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working vfork" >&5 $as_echo_n "checking for working vfork... " >&6; } if ${ac_cv_func_vfork_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_vfork_works=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Paul Eggert for this test. */ $ac_includes_default #include #ifdef HAVE_VFORK_H # include #endif /* On some sparc systems, changes by the child to local and incoming argument registers are propagated back to the parent. The compiler is told about this with #include , but some compilers (e.g. gcc -O) don't grok . Test for this by using a static variable whose address is put into a register that is clobbered by the vfork. */ static void #ifdef __cplusplus sparc_address_test (int arg) # else sparc_address_test (arg) int arg; #endif { static pid_t child; if (!child) { child = vfork (); if (child < 0) { perror ("vfork"); _exit(2); } if (!child) { arg = getpid(); write(-1, "", 0); _exit (arg); } } } int main () { pid_t parent = getpid (); pid_t child; sparc_address_test (0); child = vfork (); if (child == 0) { /* Here is another test for sparc vfork register problems. This test uses lots of local variables, at least as many local variables as main has allocated so far including compiler temporaries. 4 locals are enough for gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe. A buggy compiler should reuse the register of parent for one of the local variables, since it will think that parent can't possibly be used any more in this routine. Assigning to the local variable will thus munge parent in the parent process. */ pid_t p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(), p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid(); /* Convince the compiler that p..p7 are live; otherwise, it might use the same hardware register for all 8 local variables. */ if (p != p1 || p != p2 || p != p3 || p != p4 || p != p5 || p != p6 || p != p7) _exit(1); /* On some systems (e.g. IRIX 3.3), vfork doesn't separate parent from child file descriptors. If the child closes a descriptor before it execs or exits, this munges the parent's descriptor as well. Test for this by closing stdout in the child. */ _exit(close(fileno(stdout)) != 0); } else { int status; struct stat st; while (wait(&status) != child) ; return ( /* Was there some problem with vforking? */ child < 0 /* Did the child fail? (This shouldn't happen.) */ || status /* Did the vfork/compiler bug occur? */ || parent != getpid() /* Did the file descriptor bug occur? */ || fstat(fileno(stdout), &st) != 0 ); } } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_vfork_works=yes else ac_cv_func_vfork_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_vfork_works" >&5 $as_echo "$ac_cv_func_vfork_works" >&6; } fi; if test "x$ac_cv_func_fork_works" = xcross; then ac_cv_func_vfork_works=$ac_cv_func_vfork { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&5 $as_echo "$as_me: WARNING: result $ac_cv_func_vfork_works guessed because of cross compilation" >&2;} fi if test "x$ac_cv_func_vfork_works" = xyes; then $as_echo "#define HAVE_WORKING_VFORK 1" >>confdefs.h else $as_echo "#define vfork fork" >>confdefs.h fi if test "x$ac_cv_func_fork_works" = xyes; then $as_echo "#define HAVE_WORKING_FORK 1" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5 $as_echo_n "checking type of array argument to getgroups... " >&6; } if ${ac_cv_type_getgroups+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_type_getgroups=cross else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Thanks to Mike Rendell for this test. */ $ac_includes_default #define NGID 256 #undef MAX #define MAX(x, y) ((x) > (y) ? (x) : (y)) int main () { gid_t gidset[NGID]; int i, n; union { gid_t gval; long int lval; } val; val.lval = -1; for (i = 0; i < NGID; i++) gidset[i] = val.gval; n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, gidset); /* Exit non-zero if getgroups seems to require an array of ints. This happens when gid_t is short int but getgroups modifies an array of ints. */ return n > 0 && gidset[n] != val.gval; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_type_getgroups=gid_t else ac_cv_type_getgroups=int fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi if test $ac_cv_type_getgroups = cross; then cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then : ac_cv_type_getgroups=gid_t else ac_cv_type_getgroups=int fi rm -f conftest* fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5 $as_echo "$ac_cv_type_getgroups" >&6; } cat >>confdefs.h <<_ACEOF #define GETGROUPS_T $ac_cv_type_getgroups _ACEOF ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" if test "x$ac_cv_func_getgroups" = xyes; then : fi # If we don't yet have getgroups, see if it's in -lbsd. # This is reported to be necessary on an ITOS 3000WS running SEIUX 3.1. ac_save_LIBS=$LIBS if test $ac_cv_func_getgroups = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getgroups in -lbsd" >&5 $as_echo_n "checking for getgroups in -lbsd... " >&6; } if ${ac_cv_lib_bsd_getgroups+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lbsd $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char getgroups (); int main () { return getgroups (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_bsd_getgroups=yes else ac_cv_lib_bsd_getgroups=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_bsd_getgroups" >&5 $as_echo "$ac_cv_lib_bsd_getgroups" >&6; } if test "x$ac_cv_lib_bsd_getgroups" = xyes; then : GETGROUPS_LIB=-lbsd fi fi # Run the program to test the functionality of the system-supplied # getgroups function only if there is such a function. if test $ac_cv_func_getgroups = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working getgroups" >&5 $as_echo_n "checking for working getgroups... " >&6; } if ${ac_cv_func_getgroups_works+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_getgroups_works=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $ac_includes_default int main () { /* On Ultrix 4.3, getgroups (0, 0) always fails. */ return getgroups (0, 0) == -1; ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_getgroups_works=yes else ac_cv_func_getgroups_works=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_getgroups_works" >&5 $as_echo "$ac_cv_func_getgroups_works" >&6; } else ac_cv_func_getgroups_works=no fi if test $ac_cv_func_getgroups_works = yes; then $as_echo "#define HAVE_GETGROUPS 1" >>confdefs.h fi LIBS=$ac_save_LIBS for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5 $as_echo_n "checking for GNU libc compatible malloc... " >&6; } if ${ac_cv_func_malloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_malloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *malloc (); #endif int main () { return ! malloc (0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_malloc_0_nonnull=yes else ac_cv_func_malloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5 $as_echo "$ac_cv_func_malloc_0_nonnull" >&6; } if test $ac_cv_func_malloc_0_nonnull = yes; then : $as_echo "#define HAVE_MALLOC 1" >>confdefs.h else $as_echo "#define HAVE_MALLOC 0" >>confdefs.h case " $LIBOBJS " in *" malloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS malloc.$ac_objext" ;; esac $as_echo "#define malloc rpl_malloc" >>confdefs.h fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 $as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } if ${ac_cv_header_time+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include #include int main () { if ((struct tm *) 0) return 0; ; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : ac_cv_header_time=yes else ac_cv_header_time=no fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 $as_echo "$ac_cv_header_time" >&6; } if test $ac_cv_header_time = yes; then $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi for ac_header in $ac_header_list do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF fi done for ac_func in $ac_func_list do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working mktime" >&5 $as_echo_n "checking for working mktime... " >&6; } if ${ac_cv_func_working_mktime+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_working_mktime=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Test program from Paul Eggert and Tony Leneis. */ #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #ifdef HAVE_UNISTD_H # include #endif #ifndef HAVE_ALARM # define alarm(X) /* empty */ #endif /* Work around redefinition to rpl_putenv by other config tests. */ #undef putenv static time_t time_t_max; static time_t time_t_min; /* Values we'll use to set the TZ environment variable. */ static const char *tz_strings[] = { (const char *) 0, "TZ=GMT0", "TZ=JST-9", "TZ=EST+3EDT+2,M10.1.0/00:00:00,M2.3.0/00:00:00" }; #define N_STRINGS (sizeof (tz_strings) / sizeof (tz_strings[0])) /* Return 0 if mktime fails to convert a date in the spring-forward gap. Based on a problem report from Andreas Jaeger. */ static int spring_forward_gap () { /* glibc (up to about 1998-10-07) failed this test. */ struct tm tm; /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" instead of "TZ=America/Vancouver" in order to detect the bug even on systems that don't support the Olson extension, or don't have the full zoneinfo tables installed. */ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0"); tm.tm_year = 98; tm.tm_mon = 3; tm.tm_mday = 5; tm.tm_hour = 2; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; return mktime (&tm) != (time_t) -1; } static int mktime_test1 (time_t now) { struct tm *lt; return ! (lt = localtime (&now)) || mktime (lt) == now; } static int mktime_test (time_t now) { return (mktime_test1 (now) && mktime_test1 ((time_t) (time_t_max - now)) && mktime_test1 ((time_t) (time_t_min + now))); } static int irix_6_4_bug () { /* Based on code from Ariel Faigon. */ struct tm tm; tm.tm_year = 96; tm.tm_mon = 3; tm.tm_mday = 0; tm.tm_hour = 0; tm.tm_min = 0; tm.tm_sec = 0; tm.tm_isdst = -1; mktime (&tm); return tm.tm_mon == 2 && tm.tm_mday == 31; } static int bigtime_test (int j) { struct tm tm; time_t now; tm.tm_year = tm.tm_mon = tm.tm_mday = tm.tm_hour = tm.tm_min = tm.tm_sec = j; now = mktime (&tm); if (now != (time_t) -1) { struct tm *lt = localtime (&now); if (! (lt && lt->tm_year == tm.tm_year && lt->tm_mon == tm.tm_mon && lt->tm_mday == tm.tm_mday && lt->tm_hour == tm.tm_hour && lt->tm_min == tm.tm_min && lt->tm_sec == tm.tm_sec && lt->tm_yday == tm.tm_yday && lt->tm_wday == tm.tm_wday && ((lt->tm_isdst < 0 ? -1 : 0 < lt->tm_isdst) == (tm.tm_isdst < 0 ? -1 : 0 < tm.tm_isdst)))) return 0; } return 1; } static int year_2050_test () { /* The correct answer for 2050-02-01 00:00:00 in Pacific time, ignoring leap seconds. */ unsigned long int answer = 2527315200UL; struct tm tm; time_t t; tm.tm_year = 2050 - 1900; tm.tm_mon = 2 - 1; tm.tm_mday = 1; tm.tm_hour = tm.tm_min = tm.tm_sec = 0; tm.tm_isdst = -1; /* Use the portable POSIX.1 specification "TZ=PST8PDT,M4.1.0,M10.5.0" instead of "TZ=America/Vancouver" in order to detect the bug even on systems that don't support the Olson extension, or don't have the full zoneinfo tables installed. */ putenv ((char*) "TZ=PST8PDT,M4.1.0,M10.5.0"); t = mktime (&tm); /* Check that the result is either a failure, or close enough to the correct answer that we can assume the discrepancy is due to leap seconds. */ return (t == (time_t) -1 || (0 < t && answer - 120 <= t && t <= answer + 120)); } int main () { time_t t, delta; int i, j; /* This test makes some buggy mktime implementations loop. Give up after 60 seconds; a mktime slower than that isn't worth using anyway. */ alarm (60); for (;;) { t = (time_t_max << 1) + 1; if (t <= time_t_max) break; time_t_max = t; } time_t_min = - ((time_t) ~ (time_t) 0 == (time_t) -1) - time_t_max; delta = time_t_max / 997; /* a suitable prime number */ for (i = 0; i < N_STRINGS; i++) { if (tz_strings[i]) putenv ((char*) tz_strings[i]); for (t = 0; t <= time_t_max - delta; t += delta) if (! mktime_test (t)) return 1; if (! (mktime_test ((time_t) 1) && mktime_test ((time_t) (60 * 60)) && mktime_test ((time_t) (60 * 60 * 24)))) return 1; for (j = 1; ; j <<= 1) if (! bigtime_test (j)) return 1; else if (INT_MAX / 2 < j) break; if (! bigtime_test (INT_MAX)) return 1; } return ! (irix_6_4_bug () && spring_forward_gap () && year_2050_test ()); } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_working_mktime=yes else ac_cv_func_working_mktime=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_working_mktime" >&5 $as_echo "$ac_cv_func_working_mktime" >&6; } if test $ac_cv_func_working_mktime = no; then case " $LIBOBJS " in *" mktime.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS mktime.$ac_objext" ;; esac fi for ac_header in stdlib.h do : ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default" if test "x$ac_cv_header_stdlib_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STDLIB_H 1 _ACEOF fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible realloc" >&5 $as_echo_n "checking for GNU libc compatible realloc... " >&6; } if ${ac_cv_func_realloc_0_nonnull+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : ac_cv_func_realloc_0_nonnull=no else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #if defined STDC_HEADERS || defined HAVE_STDLIB_H # include #else char *realloc (); #endif int main () { return ! realloc (0, 0); ; return 0; } _ACEOF if ac_fn_c_try_run "$LINENO"; then : ac_cv_func_realloc_0_nonnull=yes else ac_cv_func_realloc_0_nonnull=no fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_realloc_0_nonnull" >&5 $as_echo "$ac_cv_func_realloc_0_nonnull" >&6; } if test $ac_cv_func_realloc_0_nonnull = yes; then : $as_echo "#define HAVE_REALLOC 1" >>confdefs.h else $as_echo "#define HAVE_REALLOC 0" >>confdefs.h case " $LIBOBJS " in *" realloc.$ac_objext "* ) ;; *) LIBOBJS="$LIBOBJS realloc.$ac_objext" ;; esac $as_echo "#define realloc rpl_realloc" >>confdefs.h fi for ac_func in dup2 endpwent getcwd gethostname gethostbyname getaddrinfo gethostbyname2 gettimeofday isascii memchr memmove memset regcomp select socket strcasecmp strchr strdup strerror strncasecmp strrchr strstr strtol strtoul strtoull realpath strsep do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF fi done bsdstrl_h_found="no" strl_found="no" libstrl_found="no" strl_h_found="no" for ac_header in bsd/string.h do : ac_fn_c_check_header_mongrel "$LINENO" "bsd/string.h" "ac_cv_header_bsd_string_h" "$ac_includes_default" if test "x$ac_cv_header_bsd_string_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_BSD_STRING_H 1 _ACEOF bsdstrl_h_found="yes" fi done for ac_func in strlcat strlcpy do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" if eval test \"x\$"$as_ac_var"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF strl_found="yes" else saved_LIBS="$LIBS" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strlcat" >&5 $as_echo_n "checking for library containing strlcat... " >&6; } if ${ac_cv_search_strlcat+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strlcat (); int main () { return strlcat (); ; return 0; } _ACEOF for ac_lib in '' bsd strl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_strlcat=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_strlcat+:} false; then : break fi done if ${ac_cv_search_strlcat+:} false; then : else ac_cv_search_strlcat=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strlcat" >&5 $as_echo "$ac_cv_search_strlcat" >&6; } ac_res=$ac_cv_search_strlcat if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libstrl_found="yes" else strl_found="no" fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing strlcpy" >&5 $as_echo_n "checking for library containing strlcpy... " >&6; } if ${ac_cv_search_strlcpy+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char strlcpy (); int main () { return strlcpy (); ; return 0; } _ACEOF for ac_lib in '' bsd strl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_strlcpy=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_strlcpy+:} false; then : break fi done if ${ac_cv_search_strlcpy+:} false; then : else ac_cv_search_strlcpy=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_strlcpy" >&5 $as_echo "$ac_cv_search_strlcpy" >&6; } ac_res=$ac_cv_search_strlcpy if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libstrl_found="yes" else strl_found="no" fi STRL_LIBS="$LIBS" LIBS="$saved_LIBS" fi done if test x"$libstrl_found" = x"yes" then LIBS="$LIBS $STRL_LIBS" fi # we need something above to have worked if test x"$strl_found" != x"yes" -a x"$libstrl_found" != x"yes" then as_fn_error $? "no strlcpy/strlcat found" "$LINENO" 5 fi for ac_header in strl.h do : ac_fn_c_check_header_mongrel "$LINENO" "strl.h" "ac_cv_header_strl_h" "$ac_includes_default" if test "x$ac_cv_header_strl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRL_H 1 _ACEOF strl_h_found="yes" fi done if test x"$strl_h_found" != x"yes" then strldirs="/usr/local/include/strl /usr/local/include /usr/include/strl" for d in $strldirs do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for strl.h in $d" >&5 $as_echo_n "checking for strl.h in $d... " >&6; } if test -f $d/strl.h then unset ac_cv_header_strl_h saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I$d" for ac_header in strl.h do : ac_fn_c_check_header_mongrel "$LINENO" "strl.h" "ac_cv_header_strl_h" "$ac_includes_default" if test "x$ac_cv_header_strl_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_STRL_H 1 _ACEOF strl_h_found="yes" fi done CPPFLAGS="$saved_CPPFLAGS" fi if test x"$strl_h_found" = x"yes" then CPPFLAGS="$CPPFLAGS -I$d" break fi done fi # we need to include if an installed strl.h was found and no # bsd/string.h was found if test x"$strl_h_found" = x"yes" -a x"$bsdstrl_h_found" = x"no" then $as_echo "#define USE_STRL_H 1" >>confdefs.h fi if test x"$bsdstrl_h_found" = x"yes" then $as_echo "#define USE_BSD_H 1" >>confdefs.h fi # # Checks for structure members # ac_fn_c_check_member "$LINENO" "struct sockaddr_un" "sun_len" "ac_cv_member_struct_sockaddr_un_sun_len" "#include " if test "x$ac_cv_member_struct_sockaddr_un_sun_len" = xyes; then : $as_echo "#define HAVE_SUN_LEN 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct sockaddr_in" "sin_len" "ac_cv_member_struct_sockaddr_in_sin_len" "#include " if test "x$ac_cv_member_struct_sockaddr_in_sin_len" = xyes; then : $as_echo "#define HAVE_SIN_LEN 1" >>confdefs.h fi ac_fn_c_check_member "$LINENO" "struct sockaddr_in6" "sin6_len" "ac_cv_member_struct_sockaddr_in6_sin6_len" "#include " if test "x$ac_cv_member_struct_sockaddr_in6_sin6_len" = xyes; then : $as_echo "#define HAVE_SIN6_LEN 1" >>confdefs.h fi # # Library feature string and macros # LIBOPENDKIM_FEATURE_STRING="libopendkim $PACKAGE_VERSION:" # # opendkim # notincluded="(Not enabled for this installation.)" # Check whether --enable-popauth was given. if test "${enable_popauth+set}" = set; then : enableval=$enable_popauth; if test "x$enable_popauth" = "xyes"; then : POPAUTH_MANNOTICE="" $as_echo "#define POPAUTH 1" >>confdefs.h else POPAUTH_MANNOTICE=$notincluded fi else POPAUTH_MANNOTICE=$notincluded fi notincluded="(Not enabled for this installation.)" # Check whether --enable-poll was given. if test "${enable_poll+set}" = set; then : enableval=$enable_poll; if test "x$enable_poll" = "xyes"; then : POLL_MANNOTICE="" $as_echo "#define POLL 1" >>confdefs.h else POLL_MANNOTICE=$notincluded fi else POLL_MANNOTICE=$notincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-atps was given. if test "${enable_atps+set}" = set; then : enableval=$enable_atps; if test "x$enable_atps" = "xyes"; then : $as_echo "#define _FFR_ATPS 1" >>confdefs.h ATPS_MANNOTICE="(Note: Feature is experimental.)" else ATPS_MANNOTICE=$experimentalnotincluded fi else ATPS_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-atps was given. if test "${enable_atps+set}" = set; then : enableval=$enable_atps; if test "x$enable_atps" = "xyes"; then : $as_echo "#define _FFR_ATPS 1" >>confdefs.h ATPS_MANNOTICE="(Note: Feature is experimental.)" else ATPS_MANNOTICE=$experimentalnotincluded fi else ATPS_MANNOTICE=$experimentalnotincluded fi if test "x$enable_atps" = "xyes"; then : LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING atps" fi if test x"$enable_atps" = x"yes"; then ATPS_TRUE= ATPS_FALSE='#' else ATPS_TRUE='#' ATPS_FALSE= fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-conditional was given. if test "${enable_conditional+set}" = set; then : enableval=$enable_conditional; if test "x$enable_conditional" = "xyes"; then : $as_echo "#define _FFR_CONDITIONAL 1" >>confdefs.h CONDITIONAL_MANNOTICE="(Note: Feature is experimental.)" else CONDITIONAL_MANNOTICE=$experimentalnotincluded fi else CONDITIONAL_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-conditional was given. if test "${enable_conditional+set}" = set; then : enableval=$enable_conditional; if test "x$enable_conditional" = "xyes"; then : $as_echo "#define _FFR_CONDITIONAL 1" >>confdefs.h CONDITIONAL_MANNOTICE="(Note: Feature is experimental.)" else CONDITIONAL_MANNOTICE=$experimentalnotincluded fi else CONDITIONAL_MANNOTICE=$experimentalnotincluded fi if test "x$enable_conditional" = "xyes"; then : LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING conditional" fi if test x"$enable_conditional" = x"yes"; then CONDITIONAL_TRUE= CONDITIONAL_FALSE='#' else CONDITIONAL_TRUE='#' CONDITIONAL_FALSE= fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-db_handle_pools was given. if test "${enable_db_handle_pools+set}" = set; then : enableval=$enable_db_handle_pools; if test "x$enable_db_handle_pools" = "xyes"; then : $as_echo "#define _FFR_DB_HANDLE_POOLS 1" >>confdefs.h DB_HANDLE_POOLS_MANNOTICE="(Note: Feature is experimental.)" else DB_HANDLE_POOLS_MANNOTICE=$experimentalnotincluded fi else DB_HANDLE_POOLS_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-diffheaders was given. if test "${enable_diffheaders+set}" = set; then : enableval=$enable_diffheaders; if test "x$enable_diffheaders" = "xyes"; then : $as_echo "#define _FFR_DIFFHEADERS 1" >>confdefs.h DIFFHEADERS_MANNOTICE="(Note: Feature is experimental.)" else DIFFHEADERS_MANNOTICE=$experimentalnotincluded fi else DIFFHEADERS_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-diffheaders was given. if test "${enable_diffheaders+set}" = set; then : enableval=$enable_diffheaders; if test "x$enable_diffheaders" = "xyes"; then : $as_echo "#define _FFR_DIFFHEADERS 1" >>confdefs.h DIFFHEADERS_MANNOTICE="(Note: Feature is experimental.)" else DIFFHEADERS_MANNOTICE=$experimentalnotincluded fi else DIFFHEADERS_MANNOTICE=$experimentalnotincluded fi if test "x$enable_diffheaders" = "xyes"; then : LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING diffheaders" fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-identity_header was given. if test "${enable_identity_header+set}" = set; then : enableval=$enable_identity_header; if test "x$enable_identity_header" = "xyes"; then : $as_echo "#define _FFR_IDENTITY_HEADER 1" >>confdefs.h IDENTITY_HEADER_MANNOTICE="(Note: Feature is experimental.)" else IDENTITY_HEADER_MANNOTICE=$experimentalnotincluded fi else IDENTITY_HEADER_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-ldap_caching was given. if test "${enable_ldap_caching+set}" = set; then : enableval=$enable_ldap_caching; if test "x$enable_ldap_caching" = "xyes"; then : $as_echo "#define _FFR_LDAP_CACHING 1" >>confdefs.h LDAP_CACHING_MANNOTICE="(Note: Feature is experimental.)" else LDAP_CACHING_MANNOTICE=$experimentalnotincluded fi else LDAP_CACHING_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-postgresql_reconnect_hack was given. if test "${enable_postgresql_reconnect_hack+set}" = set; then : enableval=$enable_postgresql_reconnect_hack; if test "x$enable_postgresql_reconnect_hack" = "xyes"; then : $as_echo "#define _FFR_POSTGRESQL_RECONNECT_HACK 1" >>confdefs.h POSTGRESQL_RECONNECT_HACK_MANNOTICE="(Note: Feature is experimental.)" else POSTGRESQL_RECONNECT_HACK_MANNOTICE=$experimentalnotincluded fi else POSTGRESQL_RECONNECT_HACK_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-rate_limit was given. if test "${enable_rate_limit+set}" = set; then : enableval=$enable_rate_limit; if test "x$enable_rate_limit" = "xyes"; then : $as_echo "#define _FFR_RATE_LIMIT 1" >>confdefs.h RATE_LIMIT_MANNOTICE="(Note: Feature is experimental.)" else RATE_LIMIT_MANNOTICE=$experimentalnotincluded fi else RATE_LIMIT_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-replace_rules was given. if test "${enable_replace_rules+set}" = set; then : enableval=$enable_replace_rules; if test "x$enable_replace_rules" = "xyes"; then : $as_echo "#define _FFR_REPLACE_RULES 1" >>confdefs.h REPLACE_RULES_MANNOTICE="(Note: Feature is experimental.)" else REPLACE_RULES_MANNOTICE=$experimentalnotincluded fi else REPLACE_RULES_MANNOTICE=$experimentalnotincluded fi if test x"$enable_replace_rules" = x"yes"; then REPLACE_RULES_TRUE= REPLACE_RULES_FALSE='#' else REPLACE_RULES_TRUE='#' REPLACE_RULES_FALSE= fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-reprrd was given. if test "${enable_reprrd+set}" = set; then : enableval=$enable_reprrd; if test "x$enable_reprrd" = "xyes"; then : $as_echo "#define _FFR_REPRRD 1" >>confdefs.h REPRRD_MANNOTICE="(Note: Feature is experimental.)" else REPRRD_MANNOTICE=$experimentalnotincluded fi else REPRRD_MANNOTICE=$experimentalnotincluded fi if test x"$enable_reprrd" = x"yes"; then REPRRD_TRUE= REPRRD_FALSE='#' else REPRRD_TRUE='#' REPRRD_FALSE= fi # Extract the first word of "rrdtool", so it can be a program name with args. set dummy rrdtool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_hasrrdtool+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$hasrrdtool"; then ac_cv_prog_hasrrdtool="$hasrrdtool" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_hasrrdtool="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi hasrrdtool=$ac_cv_prog_hasrrdtool if test -n "$hasrrdtool"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hasrrdtool" >&5 $as_echo "$hasrrdtool" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$enable_reprrd" = x"yes" -a x"$hasrrdtool" != x"yes" then as_fn_error $? "--enable-reprrd requires rrdtool binary, not found" "$LINENO" 5 fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-reputation was given. if test "${enable_reputation+set}" = set; then : enableval=$enable_reputation; if test "x$enable_reputation" = "xyes"; then : $as_echo "#define _FFR_REPUTATION 1" >>confdefs.h REPUTATION_MANNOTICE="(Note: Feature is experimental.)" else REPUTATION_MANNOTICE=$experimentalnotincluded fi else REPUTATION_MANNOTICE=$experimentalnotincluded fi if test x"$enable_reputation" = x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ceil" >&5 $as_echo_n "checking for library containing ceil... " >&6; } if ${ac_cv_search_ceil+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ceil (); int main () { return ceil (); ; return 0; } _ACEOF for ac_lib in '' m; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_ceil=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_ceil+:} false; then : break fi done if ${ac_cv_search_ceil+:} false; then : else ac_cv_search_ceil=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ceil" >&5 $as_echo "$ac_cv_search_ceil" >&6; } ac_res=$ac_cv_search_ceil if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi fi if test x"$enable_reputation" = x"yes"; then REPUTE_TRUE= REPUTE_FALSE='#' else REPUTE_TRUE='#' REPUTE_FALSE= fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-resign was given. if test "${enable_resign+set}" = set; then : enableval=$enable_resign; if test "x$enable_resign" = "xyes"; then : $as_echo "#define _FFR_RESIGN 1" >>confdefs.h RESIGN_MANNOTICE="(Note: Feature is experimental.)" else RESIGN_MANNOTICE=$experimentalnotincluded fi else RESIGN_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-sender_macro was given. if test "${enable_sender_macro+set}" = set; then : enableval=$enable_sender_macro; if test "x$enable_sender_macro" = "xyes"; then : $as_echo "#define _FFR_SENDER_MACRO 1" >>confdefs.h SENDER_MACRO_MANNOTICE="(Note: Feature is experimental.)" else SENDER_MACRO_MANNOTICE=$experimentalnotincluded fi else SENDER_MACRO_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-socketdb was given. if test "${enable_socketdb+set}" = set; then : enableval=$enable_socketdb; if test "x$enable_socketdb" = "xyes"; then : $as_echo "#define _FFR_SOCKETDB 1" >>confdefs.h SOCKETDB_MANNOTICE="(Note: Feature is experimental.)" else SOCKETDB_MANNOTICE=$experimentalnotincluded fi else SOCKETDB_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-stats was given. if test "${enable_stats+set}" = set; then : enableval=$enable_stats; if test "x$enable_stats" = "xyes"; then : $as_echo "#define _FFR_STATS 1" >>confdefs.h STATS_MANNOTICE="(Note: Feature is experimental.)" else STATS_MANNOTICE=$experimentalnotincluded fi else STATS_MANNOTICE=$experimentalnotincluded fi if test x"$enable_stats" = x"yes"; then STATS_TRUE= STATS_FALSE='#' else STATS_TRUE='#' STATS_FALSE= fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-statsext was given. if test "${enable_statsext+set}" = set; then : enableval=$enable_statsext; if test "x$enable_statsext" = "xyes"; then : $as_echo "#define _FFR_STATSEXT 1" >>confdefs.h STATSEXT_MANNOTICE="(Note: Feature is experimental.)" else STATSEXT_MANNOTICE=$experimentalnotincluded fi else STATSEXT_MANNOTICE=$experimentalnotincluded fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-rbl was given. if test "${enable_rbl+set}" = set; then : enableval=$enable_rbl; if test "x$enable_rbl" = "xyes"; then : $as_echo "#define _FFR_RBL 1" >>confdefs.h RBL_MANNOTICE="(Note: Feature is experimental.)" else RBL_MANNOTICE=$experimentalnotincluded fi else RBL_MANNOTICE=$experimentalnotincluded fi if test x"$enable_rbl" = x"yes"; then RBL_TRUE= RBL_FALSE='#' else RBL_TRUE='#' RBL_FALSE= fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-vbr was given. if test "${enable_vbr+set}" = set; then : enableval=$enable_vbr; if test "x$enable_vbr" = "xyes"; then : $as_echo "#define _FFR_VBR 1" >>confdefs.h VBR_MANNOTICE="(Note: Feature is experimental.)" else VBR_MANNOTICE=$experimentalnotincluded fi else VBR_MANNOTICE=$experimentalnotincluded fi if test x"$enable_vbr" = x"yes"; then VBR_TRUE= VBR_FALSE='#' else VBR_TRUE='#' VBR_FALSE= fi if test x"$enable_statsext" = x"yes" -a x"$enable_stats" != x"yes" then as_fn_error $? "--enable-statsext requires --enable-stats" "$LINENO" 5 fi experimentalnotincluded="(Experimental feature not enabled for this installation.)" # Check whether --enable-default_sender was given. if test "${enable_default_sender+set}" = set; then : enableval=$enable_default_sender; if test "x$enable_default_sender" = "xyes"; then : $as_echo "#define _FFR_DEFAULT_SENDER 1" >>confdefs.h DEFAULT_SENDER_MANNOTICE="(Note: Feature is experimental.)" else DEFAULT_SENDER_MANNOTICE=$experimentalnotincluded fi else DEFAULT_SENDER_MANNOTICE=$experimentalnotincluded fi # sendmail command # Extract the first word of "sendmail", so it can be a program name with args. set dummy sendmail; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_SENDMAIL_PATH+:} false; then : $as_echo_n "(cached) " >&6 else case $SENDMAIL_PATH in [\\/]* | ?:[\\/]*) ac_cv_path_SENDMAIL_PATH="$SENDMAIL_PATH" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR as_dummy="/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/lib:$PATH" for as_dir in $as_dummy do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_SENDMAIL_PATH="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS test -z "$ac_cv_path_SENDMAIL_PATH" && ac_cv_path_SENDMAIL_PATH="/usr/sbin/sendmail" ;; esac fi SENDMAIL_PATH=$ac_cv_path_SENDMAIL_PATH if test -n "$SENDMAIL_PATH"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SENDMAIL_PATH" >&5 $as_echo "$SENDMAIL_PATH" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi cat >>confdefs.h <<_ACEOF #define SENDMAIL_PATH "$ac_cv_path_SENDMAIL_PATH" _ACEOF # # use rpath at load time? # # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : enableval=$enable_rpath; else enable_rpath="yes" fi if test x"$enable_rpath" = x"yes"; then RPATH_TRUE= RPATH_FALSE='#' else RPATH_TRUE='#' RPATH_FALSE= fi if test x"$enable_rpath" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: Suppressing -rpath use by libtool" >&5 $as_echo "Suppressing -rpath use by libtool" >&6; } hardcode_libdir_flag_spec=" -D__LIBTOOL_NO_RPATH__ " chmod 0755 libtool fi # # test coverage/profiling stuff # # Check whether --enable-codecoverage was given. if test "${enable_codecoverage+set}" = set; then : enableval=$enable_codecoverage; fi if test x"$enable_codecoverage" = x"yes" then # gcc can do all of them; Solaris cc can only do gprof # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_hasgcc+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$hasgcc"; then ac_cv_prog_hasgcc="$hasgcc" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_hasgcc="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi hasgcc=$ac_cv_prog_hasgcc if test -n "$hasgcc"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hasgcc" >&5 $as_echo "$hasgcc" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_hascc+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$hascc"; then ac_cv_prog_hascc="$hascc" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_hascc="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi hascc=$ac_cv_prog_hascc if test -n "$hascc"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hascc" >&5 $as_echo "$hascc" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$hasgcc" != x"yes" -a x"$hascc" = x"yes" then if test x`cc -V 2>&1 | grep -c "Sun C"` = x"1" then hassuncc="yes" fi fi # figure out which profiling system to use # Extract the first word of "gprof", so it can be a program name with args. set dummy gprof; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_hasgprof+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$hasgprof"; then ac_cv_prog_hasgprof="$hasgprof" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_hasgprof="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi hasgprof=$ac_cv_prog_hasgprof if test -n "$hasgprof"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hasgprof" >&5 $as_echo "$hasgprof" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-gprof was given. if test "${with_gprof+set}" = set; then : withval=$with_gprof; hasgprof="$withval" fi if test x"$hasgcc" = x"yes" then # Extract the first word of "gcov", so it can be a program name with args. set dummy gcov; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_hasgcov+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$hasgcov"; then ac_cv_prog_hasgcov="$hasgcov" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_hasgcov="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi hasgcov=$ac_cv_prog_hasgcov if test -n "$hasgcov"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hasgcov" >&5 $as_echo "$hasgcov" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-gcov was given. if test "${with_gcov+set}" = set; then : withval=$with_gcov; hasgcov="$withval" fi # Extract the first word of "lcov", so it can be a program name with args. set dummy lcov; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_prog_haslcov+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$haslcov"; then ac_cv_prog_haslcov="$haslcov" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_haslcov="yes" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS fi fi haslcov=$ac_cv_prog_haslcov if test -n "$haslcov"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $haslcov" >&5 $as_echo "$haslcov" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi # Check whether --with-lcov was given. if test "${with_lcov+set}" = set; then : withval=$with_lcov; haslcov="$withval" fi fi # bail if none if test x"$hasgprof" != x"yes" -a \ x"$hasgcov" != x"yes" -a \ x"$haslcov" != x"yes" then as_fn_error $? "no supported test coverage packages found" "$LINENO" 5 fi # see if there's a libgcov (OpenBSD doesn't have one) if test x"$hasgcov" = x"yes" -a x"$haslcov" != x"yes" then saved_LIBS="$LIBS" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing __gcov_init" >&5 $as_echo_n "checking for library containing __gcov_init... " >&6; } if ${ac_cv_search___gcov_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char __gcov_init (); int main () { return __gcov_init (); ; return 0; } _ACEOF for ac_lib in '' gcov; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search___gcov_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search___gcov_init+:} false; then : break fi done if ${ac_cv_search___gcov_init+:} false; then : else ac_cv_search___gcov_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search___gcov_init" >&5 $as_echo "$ac_cv_search___gcov_init" >&6; } ac_res=$ac_cv_search___gcov_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi GCOV_LIBS="$LIBS" LIBS="$saved_LIBS" fi COV_CFLAGS="" COV_LDFLAGS="" COV_LIBADD="" # sun profiling if test x"$hasgprof" = x"yes" -a \ x"$hasgcov" != x"yes" -a \ x"$hassuncc" = x"yes" then COV_CFLAGS="-g -xpg" COV_LDFLAGS="-g -xpg" # non-sun profiling elif test x"$hasgprof" = x"yes" -a \ x"$hasgcov" != x"yes" -a \ x"$hassuncc" != x"yes" then COV_CFLAGS="-g -pg" COV_LDFLAGS="-g -pg" # gcov profiling elif test x"$hasgcov" = x"yes" then COV_CFLAGS="-g -fprofile-arcs -ftest-coverage" COV_LIBADD="$GCOV_LIBS" fi fi # see if profiling-enabled binaries generate profile output with the # standard name "gmon.out" or ".gmon" gprof_gmon_out="unknown" if test x"$hasgprof" = x"yes" then gprofcheck=' int main() { long x; x = random(); }' { $as_echo "$as_me:${as_lineno-$LINENO}: checking names of profiling output files" >&5 $as_echo_n "checking names of profiling output files... " >&6; } saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $COV_CFLAGS" LDFLAGS="$LDFLAGS $COV_LDFLAGS" if test "$cross_compiling" = yes; then : { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "cannot run test program while cross compiling See \`config.log' for more details" "$LINENO" 5; } else cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $gprofcheck _ACEOF if ac_fn_c_try_run "$LINENO"; then : if test -f "gmon.out" then gprof_gmon_out="yes" rm -f gmon.out { $as_echo "$as_me:${as_lineno-$LINENO}: result: gmon.out" >&5 $as_echo "gmon.out" >&6; } else gprof_gmon_out="no" rm -f *.gmon { $as_echo "$as_me:${as_lineno-$LINENO}: result: .gmon" >&5 $as_echo ".gmon" >&6; } fi else { $as_echo "$as_me:${as_lineno-$LINENO}: result: unknown" >&5 $as_echo "unknown" >&6; } fi rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ conftest.$ac_objext conftest.beam conftest.$ac_ext fi CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" fi if test x"$haslcov" = x"yes" -a x"$hasgcov" = x"yes"; then LCOV_TRUE= LCOV_FALSE='#' else LCOV_TRUE='#' LCOV_FALSE= fi if test x"$hasgcov" = x"yes"; then GCOV_TRUE= GCOV_FALSE='#' else GCOV_TRUE='#' GCOV_FALSE= fi if test x"$hasgcov" = x"yes" -a x"$haslcov" != x"yes"; then GCOV_ONLY_TRUE= GCOV_ONLY_FALSE='#' else GCOV_ONLY_TRUE='#' GCOV_ONLY_FALSE= fi if test x"$hasgprof" = x"yes" -a x"$hasgcov" != x"yes"; then GPROF_TRUE= GPROF_FALSE='#' else GPROF_TRUE='#' GPROF_FALSE= fi if test x"$gprof_gmon_out" = x"no"; then GPROF_FILENAMES_TRUE= GPROF_FILENAMES_FALSE='#' else GPROF_FILENAMES_TRUE='#' GPROF_FILENAMES_FALSE= fi # # opendkim # # Check whether --enable-filter was given. if test "${enable_filter+set}" = set; then : enableval=$enable_filter; enable_filter=$enableval else enable_filter=yes fi if test x"$enable_filter" != x"no"; then BUILD_FILTER_TRUE= BUILD_FILTER_FALSE='#' else BUILD_FILTER_TRUE='#' BUILD_FILTER_FALSE= fi # # libopendkim # notincluded="(Not enabled for this installation.)" # Check whether --enable-query_cache was given. if test "${enable_query_cache+set}" = set; then : enableval=$enable_query_cache; if test "x$enable_query_cache" = "xyes"; then : QUERY_CACHE_MANNOTICE="" $as_echo "#define QUERY_CACHE 1" >>confdefs.h else QUERY_CACHE_MANNOTICE=$notincluded fi else QUERY_CACHE_MANNOTICE=$notincluded fi if test "x$enable_query_cache" = "xyes"; then : LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING query_cache" fi # # Conditional stuff # # Check whether --enable-allsymbols was given. if test "${enable_allsymbols+set}" = set; then : enableval=$enable_allsymbols; fi if test x"$enable_allsymbols" = x"yes"; then ALL_SYMBOLS_TRUE= ALL_SYMBOLS_FALSE='#' else ALL_SYMBOLS_TRUE='#' ALL_SYMBOLS_FALSE= fi # the AM_CONDITIONAL and AC_DEFINE for USE_ARLIB are farther below, # after the Darwin checks # Check whether --enable-debug was given. if test "${enable_debug+set}" = set; then : enableval=$enable_debug; if test "x$enable_debug" = x"yes"; then : LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING debug" CFLAGS=`echo $CFLAGS | sed 's/ -O[1-9s]*//g'` fi fi if test x"$enable_debug" = x"yes"; then DEBUG_TRUE= DEBUG_FALSE='#' else DEBUG_TRUE='#' DEBUG_FALSE= fi # # gnutls # # Check whether --with-gnutls was given. if test "${with_gnutls+set}" = set; then : withval=$with_gnutls; gtpath="$withval" else gtpath="no" fi gnutls_found="no" if test \( x"$gtpath" = x"auto" -o x"$gtpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNUTLS" >&5 $as_echo_n "checking for GNUTLS... " >&6; } if test -n "$GNUTLS_CFLAGS"; then pkg_cv_GNUTLS_CFLAGS="$GNUTLS_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.11.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.11.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GNUTLS_CFLAGS=`$PKG_CONFIG --cflags "gnutls >= 2.11.7" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$GNUTLS_LIBS"; then pkg_cv_GNUTLS_LIBS="$GNUTLS_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gnutls >= 2.11.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "gnutls >= 2.11.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_GNUTLS_LIBS=`$PKG_CONFIG --libs "gnutls >= 2.11.7" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then GNUTLS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "gnutls >= 2.11.7" 2>&1` else GNUTLS_PKG_ERRORS=`$PKG_CONFIG --print-errors "gnutls >= 2.11.7" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$GNUTLS_PKG_ERRORS" >&5 gnutls_found="auto" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for GnuTLS not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for GnuTLS not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } gnutls_found="auto" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for GnuTLS not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for GnuTLS not found, trying manual search..." >&2;} else GNUTLS_CFLAGS=$pkg_cv_GNUTLS_CFLAGS GNUTLS_LIBS=$pkg_cv_GNUTLS_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } gnutls_found="pkg-config" fi elif test x"$gtpath" != x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GnuTLS library and includes in $gtpath" >&5 $as_echo "$as_me: checking for GnuTLS library and includes in $gtpath" >&6;} saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LIBS="$outer_LIBS -lgnutls $saved_LIBS" CPPFLAGS="-I$gtpath/include $saved_CPPFLAGS" CFLAGS="$saved_CFLAGS" LDFLAGS="-L$gtpath/lib $saved_LDFLAGS" for ac_header in gnutls/gnutls.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/gnutls.h" "ac_cv_header_gnutls_gnutls_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_gnutls_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_GNUTLS_H 1 _ACEOF else as_fn_error $? "required GnuTLS header not found" "$LINENO" 5 fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gnutls_global_init" >&5 $as_echo_n "checking for library containing gnutls_global_init... " >&6; } if ${ac_cv_search_gnutls_global_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_global_init (); int main () { return gnutls_global_init (); ; return 0; } _ACEOF for ac_lib in '' gnutls; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -lnettle -lgmp -ldl $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gnutls_global_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gnutls_global_init+:} false; then : break fi done if ${ac_cv_search_gnutls_global_init+:} false; then : else ac_cv_search_gnutls_global_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gnutls_global_init" >&5 $as_echo "$ac_cv_search_gnutls_global_init" >&6; } ac_res=$ac_cv_search_gnutls_global_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "libgnutls not found" "$LINENO" 5 fi LIBCRYPTO_CPPFLAGS="-I$gtpath/include" LIBCRYPTO_LIBDIRS="-L$gtpath/lib" LIBCRYPTO_LIBS="-lgnutls" CFLAGS="$saved_CFLAGS" CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" gnutls_found="yes" fi if test x"$gnutls_found" = x"pkg-config" then LIBCRYPTO_CPPFLAGS="$GNUTLS_CFLAGS" LIBCRYPTO_LDFLAGS="" LIBCRYPTO_LIBS="$GNUTLS_LIBS" gnutls_found="yes" fi if test x"$gtpath" = x"yes" -a x"$gnutls_found" = x"auto" then gcdirs="/usr/local /usr" for d in $gcdirs do { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GnuTLS library and includes in $d" >&5 $as_echo "$as_me: checking for GnuTLS library and includes in $d" >&6;} saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LIBS="$outer_LIBS -lgnutls $saved_LIBS" CPPFLAGS="-I$d/include $saved_CPPFLAGS" CFLAGS="$saved_CFLAGS" LDFLAGS="$outer_LDFLAGS -L$d/lib $saved_LDFLAGS" gnutls_h_found="no" gnutls_lib_found="no" for ac_header in gnutls/gnutls.h do : ac_fn_c_check_header_mongrel "$LINENO" "gnutls/gnutls.h" "ac_cv_header_gnutls_gnutls_h" "$ac_includes_default" if test "x$ac_cv_header_gnutls_gnutls_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_GNUTLS_GNUTLS_H 1 _ACEOF gnutls_h_found="yes" fi done { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gnutls_global_init" >&5 $as_echo_n "checking for library containing gnutls_global_init... " >&6; } if ${ac_cv_search_gnutls_global_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char gnutls_global_init (); int main () { return gnutls_global_init (); ; return 0; } _ACEOF for ac_lib in '' gnutls; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -lnettle -lgmp $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_gnutls_global_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_gnutls_global_init+:} false; then : break fi done if ${ac_cv_search_gnutls_global_init+:} false; then : else ac_cv_search_gnutls_global_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gnutls_global_init" >&5 $as_echo "$ac_cv_search_gnutls_global_init" >&6; } ac_res=$ac_cv_search_gnutls_global_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" gnutls_lib_found="yes" fi CFLAGS="$saved_CFLAGS" CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$gnutls_h_found" = x"yes" -a \ x"$gnutls_lib_found" = x"yes" then LIBCRYPTO_CPPFLAGS="-I$d/include" LIBCRYPTO_LIBDIRS="-L$d/lib" LIBCRYPTO_LIBS="-lgnutls" gnutls_found="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: libgnutls found in $d" >&5 $as_echo "$as_me: libgnutls found in $d" >&6;} break else { $as_echo "$as_me:${as_lineno-$LINENO}: not found in $d" >&5 $as_echo "$as_me: not found in $d" >&6;} fi done if test x"$gnutls_found" != x"yes" then as_fn_error $? "GnuTLS not found" "$LINENO" 5 fi fi if test x"$gnutls_found" = x"yes" then $as_echo "#define USE_GNUTLS 1" >>confdefs.h saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$LIBCRYPTO_CPPFLAGS $saved_CPPFLAGS" versioncheck=' #include #if GNUTLS_VERSION_NUMBER < 0x020b07 # error GnuTLS 2.11.7 or later required #endif int main() { return 0; }' { $as_echo "$as_me:${as_lineno-$LINENO}: checking your GnuTLS version" >&5 $as_echo_n "checking your GnuTLS version... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $versioncheck _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} as_fn_error $? "GnuTLS must be at least version 2.11.7 See \`config.log' for more details" "$LINENO" 5; } fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext sha256check=' #include int main() { int x = GNUTLS_DIG_SHA256; }' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether your GnuTLS supports SHA256" >&5 $as_echo_n "checking whether your GnuTLS supports SHA256... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ $sha256check _ACEOF if ac_fn_c_try_link "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } $as_echo "#define HAVE_SHA256 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SHA256 is required for DKIM but is not supported with your version of GnuTLS" >&5 $as_echo "$as_me: WARNING: SHA256 is required for DKIM but is not supported with your version of GnuTLS" >&2;} fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext CPPFLAGS="$saved_CPPFLAGS" fi if test x"$gnutls_found" = x"yes"; then USE_GNUTLS_TRUE= USE_GNUTLS_FALSE='#' else USE_GNUTLS_TRUE='#' USE_GNUTLS_FALSE= fi # # OpenSSL # # Check whether --with-openssl was given. if test "${with_openssl+set}" = set; then : withval=$with_openssl; sslpath="$withval" else sslpath="auto" fi openssl_found="no" if test x"$gnutls_found" = x"yes" then sslpath="skip" openssl_found="skip" fi if test \( "$sslpath" = "auto" -o x"$sslpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBCRYPTO" >&5 $as_echo_n "checking for LIBCRYPTO... " >&6; } if test -n "$LIBCRYPTO_CFLAGS"; then pkg_cv_LIBCRYPTO_CFLAGS="$LIBCRYPTO_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBCRYPTO_CFLAGS=`$PKG_CONFIG --cflags "openssl >= 0.9.7" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBCRYPTO_LIBS"; then pkg_cv_LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openssl >= 0.9.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "openssl >= 0.9.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBCRYPTO_LIBS=`$PKG_CONFIG --libs "openssl >= 0.9.7" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBCRYPTO_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "openssl >= 0.9.7" 2>&1` else LIBCRYPTO_PKG_ERRORS=`$PKG_CONFIG --print-errors "openssl >= 0.9.7" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBCRYPTO_PKG_ERRORS" >&5 openssl_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for openssl not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for openssl not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } openssl_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for openssl not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for openssl not found, trying manual search..." >&2;} else LIBCRYPTO_CFLAGS=$pkg_cv_LIBCRYPTO_CFLAGS LIBCRYPTO_LIBS=$pkg_cv_LIBCRYPTO_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } openssl_found="yes" fi elif test "$sslpath" != "auto" -a x"$sslpath" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL includes" >&5 $as_echo_n "checking for OpenSSL includes... " >&6; } if test -f $sslpath/include/openssl/opensslv.h then LIBCRYPTO_CPPFLAGS="-I$sslpath/include" LIBCRYPTO_CFLAGS="" LIBCRYPTO_LIBDIRS="-L$sslpath/lib" LIBCRYPTO_LIBS="-lssl -lcrypto" openssl_found=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sslpath" >&5 $as_echo "$sslpath" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x"$openssl_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenSSL library and includes" >&5 $as_echo_n "checking for OpenSSL library and includes... " >&6; } ssldirs="/usr/local/ssl /usr/local /usr/sfw /opt/local /usr" if test "$sslpath" = "auto" -o "$sslpath" = "yes" then for d in $ssldirs do if test -f $d/include/openssl/opensslv.h then sslpath=$d openssl_found=yes break fi done fi case "$sslpath" in no) as_fn_error $? "OpenSSL is required" "$LINENO" 5 ;; auto) as_fn_error $? "OpenSSL not found" "$LINENO" 5 ;; */*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $sslpath" >&5 $as_echo "$sslpath" >&6; } ;; *) as_fn_error $? "OpenSSL not found" "$LINENO" 5 ;; esac LIBCRYPTO_CPPFLAGS="-I$sslpath/include" LIBCRYPTO_CFLAGS="" LIBCRYPTO_LIBDIRS="-L$sslpath/lib" LIBCRYPTO_LIBS="-lssl -lcrypto" fi if test x"$openssl_found" = x"yes" then saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LIBS="$outer_LIBS $LIBCRYPTO_LIBS $saved_LIBS" CPPFLAGS="$LIBCRYPTO_CPPFLAGS $saved_CPPFLAGS" CFLAGS="$LIBCRYPTO_CFLAGS $saved_CFLAGS" LDFLAGS="$outer_LDFLAGS $LIBCRYPTO_LIBDIRS $saved_LDFLAGS" for ac_header in openssl/bio.h openssl/conf.h openssl/crypto.h openssl/err.h openssl/evp.h openssl/md5.h openssl/opensslv.h openssl/pem.h openssl/rsa.h openssl/sha.h openssl/ssl.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF else as_fn_error $? "required OpenSSL header not found" "$LINENO" 5 fi done # -ldl is needed to assist with compilation of static openssl libraries. # It appears to need dl for opening engine plugins. It fails at load # time It also fails to build on FreeBSD if enabled by default. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ERR_peek_error" >&5 $as_echo_n "checking for library containing ERR_peek_error... " >&6; } if ${ac_cv_search_ERR_peek_error+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ERR_peek_error (); int main () { return ERR_peek_error (); ; return 0; } _ACEOF for ac_lib in '' crypto; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_ERR_peek_error=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_ERR_peek_error+:} false; then : break fi done if ${ac_cv_search_ERR_peek_error+:} false; then : else ac_cv_search_ERR_peek_error=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ERR_peek_error" >&5 $as_echo "$ac_cv_search_ERR_peek_error" >&6; } ac_res=$ac_cv_search_ERR_peek_error if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "libcrypto not found" "$LINENO" 5 fi cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main () { SSL_library_init(); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : od_have_ossl="yes"; else od_have_ossl="no"; fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext if test x"$od_have_ossl" = x"no" then if test x"$enable_shared" = x"yes" then as_fn_error $? "Cannot build shared opendkim against static openssl libraries. Configure with --disable-shared to get this working or obtain a shared libssl library for opendkim to use." "$LINENO" 5 fi LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS -ldl" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing SSL_library_init" >&5 $as_echo_n "checking for library containing SSL_library_init... " >&6; } if ${ac_cv_search_SSL_library_init+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char SSL_library_init (); int main () { return SSL_library_init (); ; return 0; } _ACEOF for ac_lib in '' ssl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -ldl $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_SSL_library_init=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_SSL_library_init+:} false; then : break fi done if ${ac_cv_search_SSL_library_init+:} false; then : else ac_cv_search_SSL_library_init=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_SSL_library_init" >&5 $as_echo "$ac_cv_search_SSL_library_init" >&6; } ac_res=$ac_cv_search_SSL_library_init if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" else as_fn_error $? "libssl not found" "$LINENO" 5 fi fi ac_fn_c_check_decl "$LINENO" "EVP_PKEY_ED25519" "ac_cv_have_decl_EVP_PKEY_ED25519" " #include #include " if test "x$ac_cv_have_decl_EVP_PKEY_ED25519" = xyes; then : $as_echo "#define HAVE_ED25519 1" >>confdefs.h fi ac_fn_c_check_decl "$LINENO" "SHA256_DIGEST_LENGTH" "ac_cv_have_decl_SHA256_DIGEST_LENGTH" " #include #include " if test "x$ac_cv_have_decl_SHA256_DIGEST_LENGTH" = xyes; then : $as_echo "#define HAVE_SHA256 1" >>confdefs.h else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SHA256 is required for DKIM but is not supported with your version of OpenSSL" >&5 $as_echo "$as_me: WARNING: SHA256 is required for DKIM but is not supported with your version of OpenSSL" >&2;} fi CFLAGS="$saved_CFLAGS" CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" fi # # libmilter # { $as_echo "$as_me:${as_lineno-$LINENO}: checking for milter library and includes" >&5 $as_echo_n "checking for milter library and includes... " >&6; } # Check whether --with-milter was given. if test "${with_milter+set}" = set; then : withval=$with_milter; milterpath="$withval" else milterpath="auto" fi if test x"$enable_filter" = x"no" then milterpath="no" fi if test "$milterpath" = "auto" -o "$milterpath" = "yes" then milterdirs="/usr/local /opt/local /usr" for d in $milterdirs do if test -f $d/include/libmilter/mfapi.h then milterpath=$d break fi done fi case "$milterpath" in no) if test x"$enable_filter" = x"yes" then as_fn_error $? "milter is required" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: disabled" >&5 $as_echo "disabled" >&6; } ;; auto) as_fn_error $? "milter not found" "$LINENO" 5 ;; */*) if ! test -f $milterpath/include/libmilter/mfapi.h then as_fn_error $? "milter includes not found at $milterpath" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $milterpath" >&5 $as_echo "$milterpath" >&6; } ;; *) as_fn_error $? "milter not found" "$LINENO" 5 ;; esac LIBMILTER_INCDIRS="" LIBMILTER_LIBDIRS="" LIBMILTER_LIBS="" if test x"$milterpath" != x"no" then LIBMILTER_INCDIRS="-I$milterpath/include" saved_CC="$CC" saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" CC="$PTHREAD_CC" LIBS="$outer_LIBS $PTHREAD_LIBS $saved_LIBS" CPPFLAGS="$LIBMILTER_INCDIRS $saved_CPPFLAGS" CFLAGS="$PTHREAD_CFLAGS $saved_CFLAGS" LDFLAGS="$outer_LDFLAGS $PTHREAD_CFLAGS $saved_LDFLAGS" breakloop="no" for d in lib lib64 lib/libmilter do unset ac_cv_search_smfi_register LDFLAGS="$outer_LDFLAGS $PTHREAD_CFLAGS -L$milterpath/$d $saved_LDFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing smfi_register" >&5 $as_echo_n "checking for library containing smfi_register... " >&6; } if ${ac_cv_search_smfi_register+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char smfi_register (); int main () { return smfi_register (); ; return 0; } _ACEOF for ac_lib in '' milter; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_smfi_register=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_smfi_register+:} false; then : break fi done if ${ac_cv_search_smfi_register+:} false; then : else ac_cv_search_smfi_register=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_smfi_register" >&5 $as_echo "$ac_cv_search_smfi_register" >&6; } ac_res=$ac_cv_search_smfi_register if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" LIBMILTER_LIBDIRS="-L$milterpath/$d" LIBMILTER_LIBS="-lmilter" breakloop="yes" fi ac_fn_c_check_func "$LINENO" "smfi_insheader" "ac_cv_func_smfi_insheader" if test "x$ac_cv_func_smfi_insheader" = xyes; then : $as_echo "#define HAVE_SMFI_INSHEADER 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "smfi_opensocket" "ac_cv_func_smfi_opensocket" if test "x$ac_cv_func_smfi_opensocket" = xyes; then : $as_echo "#define HAVE_SMFI_OPENSOCKET 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "smfi_progress" "ac_cv_func_smfi_progress" if test "x$ac_cv_func_smfi_progress" = xyes; then : $as_echo "#define HAVE_SMFI_PROGRESS 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "smfi_setsymlist" "ac_cv_func_smfi_setsymlist" if test "x$ac_cv_func_smfi_setsymlist" = xyes; then : $as_echo "#define HAVE_SMFI_SETSYMLIST 1" >>confdefs.h fi ac_fn_c_check_func "$LINENO" "smfi_version" "ac_cv_func_smfi_version" if test "x$ac_cv_func_smfi_version" = xyes; then : $as_echo "#define HAVE_SMFI_VERSION 1" >>confdefs.h fi if test x"$breakloop" = x"yes" then break fi done if test x"$LIBMILTER_LIBDIRS" = x"" then as_fn_error $? "libmilter not found" "$LINENO" 5 fi CC="$saved_CC" CPPFLAGS="$saved_CPPFLAGS" CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" fi # # librrd # # Check whether --with-librrd was given. if test "${with_librrd+set}" = set; then : withval=$with_librrd; librrdpath="$withval" else librrdpath="no" fi librrd_found="no" if test x"$enable_reprrd" = x"yes" -a x"$librrdpath" = x"no" then librrdpath="auto" fi if test \( x"$librrdpath" = x"auto" -o x"$librrdpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RRDTOOL" >&5 $as_echo_n "checking for RRDTOOL... " >&6; } if test -n "$RRDTOOL_CFLAGS"; then pkg_cv_RRDTOOL_CFLAGS="$RRDTOOL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librrd\""; } >&5 ($PKG_CONFIG --exists --print-errors "librrd") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_RRDTOOL_CFLAGS=`$PKG_CONFIG --cflags "librrd" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$RRDTOOL_LIBS"; then pkg_cv_RRDTOOL_LIBS="$RRDTOOL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"librrd\""; } >&5 ($PKG_CONFIG --exists --print-errors "librrd") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_RRDTOOL_LIBS=`$PKG_CONFIG --libs "librrd" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then RRDTOOL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "librrd" 2>&1` else RRDTOOL_PKG_ERRORS=`$PKG_CONFIG --print-errors "librrd" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$RRDTOOL_PKG_ERRORS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for rrdtool not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for rrdtool not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for rrdtool not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for rrdtool not found, trying manual search..." >&2;} else RRDTOOL_CFLAGS=$pkg_cv_RRDTOOL_CFLAGS RRDTOOL_LIBS=$pkg_cv_RRDTOOL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } librrd_found="yes" fi fi if test \( x"$librrdpath" = x"auto" -o x"$librrdpath" = x"yes" \) -a x"$librrd_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for librrd" >&5 $as_echo_n "checking for librrd... " >&6; } librrddirs="/usr /usr/local" for d in $librrddirs do if test -f $d/include/rrd.h then librrdpath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } RRDTOOL_CFLAGS="-I$librrdpath/include" RRDTOOL_LIBS="-L$librrdpath/lib -lrrd" librrd_found="yes" break fi done if test x"$RRDTOOL_LIBS" = x"" then as_fn_error $? "not found" "$LINENO" 5 fi elif test x"$librrdpath" != x"no" -a x"$librrd_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for librrd" >&5 $as_echo_n "checking for librrd... " >&6; } if test -f $librrdpath/include/rrd.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $librrdpath" >&5 $as_echo "$librrdpath" >&6; } RRDTOOL_CFLAGS="-I$librrdpath/include" RRDTOOL_LIBS="-L$librrdpath/lib -lrrd" librrd_found="yes" else as_fn_error $? "not found at $librrdpath" "$LINENO" 5 fi fi if test x"$librrdpath" = x"no" -o x"$librrd_found" = x"no" then RRDTOOL_CFLAGS="" RRDTOOL_LIBS="" LIBRRD_MANNOTICE="(Not enabled for this installation.)" else $as_echo "#define USE_RRD 1" >>confdefs.h LIBRRD_MANNOTICE="" fi if test x"$librrdpath" != x"no"; then USE_RRD_TRUE= USE_RRD_FALSE='#' else USE_RRD_TRUE='#' USE_RRD_FALSE= fi # # libmemcached # # Check whether --with-libmemcached was given. if test "${with_libmemcached+set}" = set; then : withval=$with_libmemcached; libmcdpath="$withval" else libmcdpath="no" fi libmemcache_found="no" if test \( x"$libmcdpath" = x"auto" -o x"$libmcdpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBMEMCACHED" >&5 $as_echo_n "checking for LIBMEMCACHED... " >&6; } if test -n "$LIBMEMCACHED_CFLAGS"; then pkg_cv_LIBMEMCACHED_CFLAGS="$LIBMEMCACHED_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmemcached >= 0.36\""; } >&5 ($PKG_CONFIG --exists --print-errors "libmemcached >= 0.36") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBMEMCACHED_CFLAGS=`$PKG_CONFIG --cflags "libmemcached >= 0.36" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBMEMCACHED_LIBS"; then pkg_cv_LIBMEMCACHED_LIBS="$LIBMEMCACHED_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmemcached >= 0.36\""; } >&5 ($PKG_CONFIG --exists --print-errors "libmemcached >= 0.36") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBMEMCACHED_LIBS=`$PKG_CONFIG --libs "libmemcached >= 0.36" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBMEMCACHED_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libmemcached >= 0.36" 2>&1` else LIBMEMCACHED_PKG_ERRORS=`$PKG_CONFIG --print-errors "libmemcached >= 0.36" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBMEMCACHED_PKG_ERRORS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libmemcached not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libmemcached not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libmemcached not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libmemcached not found, trying manual search..." >&2;} else LIBMEMCACHED_CFLAGS=$pkg_cv_LIBMEMCACHED_CFLAGS LIBMEMCACHED_LIBS=$pkg_cv_LIBMEMCACHED_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } libmemcache_found="yes" LIBMEMCACHED_INCDIRS="$LIBMEMCACHED_CFLAGS" fi fi if test \( x"$libmcdpath" = x"auto" -o x"$libmcdpath" = x"yes" \) -a x"$libmemcache_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmemcached" >&5 $as_echo_n "checking for libmemcached... " >&6; } libmcddirs="/usr /usr/local" for d in $libmcddirs do if test -f $d/include/libmemcached/memcached.h then libmcdpath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBMEMCACHED_INCDIRS="-I$libmcdpath/include" LIBMEMCACHED_LIBDIRS="-L$libmcdpath/lib" LIBMEMCACHED_LIBS="-lmemcached" libmemcache_found="yes" break fi done if test x"$LIBMEMCACHED_LIBS" = x"" then as_fn_error $? "not found" "$LINENO" 5 fi elif test x"$libmcdpath" != x"no" -a x"$libmemcache_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libmemcached" >&5 $as_echo_n "checking for libmemcached... " >&6; } if test -f $libmcdpath/include/libmemcached/memcached.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libmcdpath" >&5 $as_echo "$libmcdpath" >&6; } LIBMEMCACHED_INCDIRS="-I$libmcdpath/include" LIBMEMCACHED_LIBDIRS="-L$libmcdpath/lib" LIBMEMCACHED_LIBS="-lmemcached" libmemcache_found="yes" else as_fn_error $? "not found at $libmcdpath" "$LINENO" 5 fi fi # confirm memcached_return_t is defined if test x"$libmemcache_found" = x"yes" then saved_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBMEMCACHED_INCDIRS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for memcached_return_t" >&5 $as_echo_n "checking for memcached_return_t... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int main() { memcached_return_t x; return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else as_fn_error $? "libmemcached version 0.36 or later required" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi if test x"$libmcdpath" = x"no" -o x"$libmemcache_found" = x"no" then LIBMEMCACHED_INCDIRS="" LIBMEMCACHED_LIBDIRS="" LIBMEMCACHED_LIBS="" LIBMEMCACHED_MANNOTICE="(Not enabled for this installation.)" else $as_echo "#define USE_LIBMEMCACHED 1" >>confdefs.h LIBMEMCACHED_MANNOTICE="" fi if test x"$libmcdpath" != x"no"; then USE_LIBMEMCACHED_TRUE= USE_LIBMEMCACHED_FALSE='#' else USE_LIBMEMCACHED_TRUE='#' USE_LIBMEMCACHED_FALSE= fi # # libunbound # # Check whether --with-unbound was given. if test "${with_unbound+set}" = set; then : withval=$with_unbound; unboundpath="$withval" else unboundpath="no" fi if test x"$unboundpath" = x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libunbound" >&5 $as_echo_n "checking for libunbound... " >&6; } unbounddirs="/usr /usr/local" for d in $unbounddirs do if test -f $d/include/unbound.h then unboundpath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBUNBOUND_INCDIRS="-I$unboundpath/include" LIBUNBOUND_LIBDIRS="-L$unboundpath/lib" LIBUNBOUND_LIBS="-lunbound" break fi done if test x"$LIBUNBOUND_LIBS" = x"" then as_fn_error $? "not found" "$LINENO" 5 fi elif test x"$unboundpath" = x"no" then LIBUNBOUND_INCDIRS="" LIBUNBOUND_LIBDIRS="" LIBUNBOUND_LIBS="" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libunbound" >&5 $as_echo_n "checking for libunbound... " >&6; } if test -f $unboundpath/include/unbound.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $unboundpath" >&5 $as_echo "$unboundpath" >&6; } LIBUNBOUND_INCDIRS="-I$unboundpath/include" LIBUNBOUND_LIBDIRS="-L$unboundpath/lib" LIBUNBOUND_LIBS="-lunbound" else as_fn_error $? "not found at $unboundpath" "$LINENO" 5 fi fi if test x"$unboundpath" = x"no" then UNBOUND_MANNOTICE="(Not enabled for this installation.)" else $as_echo "#define USE_UNBOUND 1" >>confdefs.h UNBOUND_MANNOTICE="" fi if test x"$unboundpath" != x"no"; then USE_UNBOUND_TRUE= USE_UNBOUND_FALSE='#' else USE_UNBOUND_TRUE='#' USE_UNBOUND_FALSE= fi # unbound also needs ldns # Check whether --with-ldns was given. if test "${with_ldns+set}" = set; then : withval=$with_ldns; ldnspath="$withval" else ldnspath="no" fi LIBLDNS_LIBS="" LIBLDNS_LIBDIRS="" if test x"$ldnspath" = x"yes" then ldns_found="no" ldnsdirs="/usr /usr/local" for d in $ldnsdirs do unset ac_cv_search_ldns_rr_new saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ldns_rr_new" >&5 $as_echo_n "checking for library containing ldns_rr_new... " >&6; } if ${ac_cv_search_ldns_rr_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ldns_rr_new (); int main () { return ldns_rr_new (); ; return 0; } _ACEOF for ac_lib in '' ldns; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_ldns_rr_new=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_ldns_rr_new+:} false; then : break fi done if ${ac_cv_search_ldns_rr_new+:} false; then : else ac_cv_search_ldns_rr_new=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ldns_rr_new" >&5 $as_echo "$ac_cv_search_ldns_rr_new" >&6; } ac_res=$ac_cv_search_ldns_rr_new if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ldns_found="yes" fi LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$ldns_found" = x"yes" then LIBLDNS_LIBDIRS="-L$d/lib" LIBLDNS_LIBS="-lldns" break fi done if test x"$LIBLDNS_LIBS" = x"" then as_fn_error $? "libldns not found" "$LINENO" 5 fi elif test x"$ldnspath" != x"no" then ldns_found="no" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing ldns_rr_new" >&5 $as_echo_n "checking for library containing ldns_rr_new... " >&6; } if ${ac_cv_search_ldns_rr_new+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char ldns_rr_new (); int main () { return ldns_rr_new (); ; return 0; } _ACEOF for ac_lib in '' ldns; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_ldns_rr_new=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_ldns_rr_new+:} false; then : break fi done if ${ac_cv_search_ldns_rr_new+:} false; then : else ac_cv_search_ldns_rr_new=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_ldns_rr_new" >&5 $as_echo "$ac_cv_search_ldns_rr_new" >&6; } ac_res=$ac_cv_search_ldns_rr_new if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" ldns_found="yes" fi LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$ldns_found" = x"yes" then LIBLDNS_LIBDIRS="-L$d/lib" LIBLDNS_LIBS="-lldns" break else as_fn_error $? "libldns not found in $d" "$LINENO" 5 fi fi # unbound may also need libevent # Check whether --with-libevent was given. if test "${with_libevent+set}" = set; then : withval=$with_libevent; libeventpath="$withval" else libeventpath="no" fi LIBEVENT_LIBS="" LIBEVENT_LIBDIRS="" if test x"$libevent" = x"yes" then libevent_found="no" libeventdirs="/usr /usr/local" for d in $libeventdirs do unset ac_cv_search_libevent_rr_new saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing evutil_vsnprintf" >&5 $as_echo_n "checking for library containing evutil_vsnprintf... " >&6; } if ${ac_cv_search_evutil_vsnprintf+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char evutil_vsnprintf (); int main () { return evutil_vsnprintf (); ; return 0; } _ACEOF for ac_lib in '' event; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_evutil_vsnprintf=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_evutil_vsnprintf+:} false; then : break fi done if ${ac_cv_search_evutil_vsnprintf+:} false; then : else ac_cv_search_evutil_vsnprintf=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_evutil_vsnprintf" >&5 $as_echo "$ac_cv_search_evutil_vsnprintf" >&6; } ac_res=$ac_cv_search_evutil_vsnprintf if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libevent_found="yes" fi LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$libevent_found" = x"yes" then LIBEVENT_LIBDIRS="-L$d/lib" LIBEVENT_LIBS="-levent" break fi done if test x"$LIBEVENT_LIBS" = x"" then as_fn_error $? "libevent not found" "$LINENO" 5 fi elif test x"$libeventpath" != x"no" then libevent_found="no" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing evutil_vsnprintf" >&5 $as_echo_n "checking for library containing evutil_vsnprintf... " >&6; } if ${ac_cv_search_evutil_vsnprintf+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char evutil_vsnprintf (); int main () { return evutil_vsnprintf (); ; return 0; } _ACEOF for ac_lib in '' event; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_evutil_vsnprintf=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_evutil_vsnprintf+:} false; then : break fi done if ${ac_cv_search_evutil_vsnprintf+:} false; then : else ac_cv_search_evutil_vsnprintf=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_evutil_vsnprintf" >&5 $as_echo "$ac_cv_search_evutil_vsnprintf" >&6; } ac_res=$ac_cv_search_evutil_vsnprintf if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libevent_found="yes" fi LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$libevent_found" = x"yes" then LIBEVENT_LIBDIRS="-L$d/lib" LIBEVENT_LIBS="-levent" break else as_fn_error $? "libevent not found in $d" "$LINENO" 5 fi fi # # libtre # # Check whether --with-tre was given. if test "${with_tre+set}" = set; then : withval=$with_tre; trepath="$withval" else trepath="auto" fi tre_found="no" LIBTRE_CPPFLAGS="" LIBTRE_LIBS="" if test x"$enable_diffheaders" != x"yes" then trepath="no" fi if test \( x"$trepath" = x"auto" -o x"$trepath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBTRE" >&5 $as_echo_n "checking for LIBTRE... " >&6; } if test -n "$LIBTRE_CFLAGS"; then pkg_cv_LIBTRE_CFLAGS="$LIBTRE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tre >= 0.8.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "tre >= 0.8.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBTRE_CFLAGS=`$PKG_CONFIG --cflags "tre >= 0.8.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBTRE_LIBS"; then pkg_cv_LIBTRE_LIBS="$LIBTRE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tre >= 0.8.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "tre >= 0.8.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBTRE_LIBS=`$PKG_CONFIG --libs "tre >= 0.8.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBTRE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "tre >= 0.8.0" 2>&1` else LIBTRE_PKG_ERRORS=`$PKG_CONFIG --print-errors "tre >= 0.8.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBTRE_PKG_ERRORS" >&5 pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBTRE" >&5 $as_echo_n "checking for LIBTRE... " >&6; } if test -n "$LIBTRE_CFLAGS"; then pkg_cv_LIBTRE_CFLAGS="$LIBTRE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tre >= 0.7.5\""; } >&5 ($PKG_CONFIG --exists --print-errors "tre >= 0.7.5") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBTRE_CFLAGS=`$PKG_CONFIG --cflags "tre >= 0.7.5" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBTRE_LIBS"; then pkg_cv_LIBTRE_LIBS="$LIBTRE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tre >= 0.7.5\""; } >&5 ($PKG_CONFIG --exists --print-errors "tre >= 0.7.5") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBTRE_LIBS=`$PKG_CONFIG --libs "tre >= 0.7.5" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBTRE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "tre >= 0.7.5" 2>&1` else LIBTRE_PKG_ERRORS=`$PKG_CONFIG --print-errors "tre >= 0.7.5" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBTRE_PKG_ERRORS" >&5 tre_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } tre_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&2;} else LIBTRE_CFLAGS=$pkg_cv_LIBTRE_CFLAGS LIBTRE_LIBS=$pkg_cv_LIBTRE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } tre_found="yes" $as_echo "#define TRE_PRE_080 1" >>confdefs.h fi elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBTRE" >&5 $as_echo_n "checking for LIBTRE... " >&6; } if test -n "$LIBTRE_CFLAGS"; then pkg_cv_LIBTRE_CFLAGS="$LIBTRE_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tre >= 0.7.5\""; } >&5 ($PKG_CONFIG --exists --print-errors "tre >= 0.7.5") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBTRE_CFLAGS=`$PKG_CONFIG --cflags "tre >= 0.7.5" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBTRE_LIBS"; then pkg_cv_LIBTRE_LIBS="$LIBTRE_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"tre >= 0.7.5\""; } >&5 ($PKG_CONFIG --exists --print-errors "tre >= 0.7.5") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBTRE_LIBS=`$PKG_CONFIG --libs "tre >= 0.7.5" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBTRE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "tre >= 0.7.5" 2>&1` else LIBTRE_PKG_ERRORS=`$PKG_CONFIG --print-errors "tre >= 0.7.5" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBTRE_PKG_ERRORS" >&5 tre_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } tre_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libtre >= 0.7.5 not found, trying manual search..." >&2;} else LIBTRE_CFLAGS=$pkg_cv_LIBTRE_CFLAGS LIBTRE_LIBS=$pkg_cv_LIBTRE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } tre_found="yes" $as_echo "#define TRE_PRE_080 1" >>confdefs.h fi else LIBTRE_CFLAGS=$pkg_cv_LIBTRE_CFLAGS LIBTRE_LIBS=$pkg_cv_LIBTRE_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } tre_found="yes" fi fi if test x"$tre_found" = x"no" -a x"$trepath" != x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libtre" >&5 $as_echo_n "checking for libtre... " >&6; } if test x"$trepath" != x"auto" -a x"$trepath" != x"yes" then if test -f "$trepath/include/tre/tre.h" then tre_found="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $trepath" >&5 $as_echo "$trepath" >&6; } LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" elif test -f "$trepath/include/tre/regex.h" then tre_found="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $trepath (old version)" >&5 $as_echo "$trepath (old version)" >&6; } $as_echo "#define TRE_PRE_080 1" >>confdefs.h LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" else as_fn_error $? "\"not found at $trepath\"" "$LINENO" 5 fi else tredirs="/usr /usr/local" for d in $tredirs do if test -f $d/include/tre/tre.h then trepath=$d tre_found="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" break elif test -f $d/include/tre/regex.h then trepath=$d tre_found="yes" { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d (old version)" >&5 $as_echo "$d (old version)" >&6; } $as_echo "#define TRE_PRE_080 1" >>confdefs.h LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" break fi done if test x"$tre_found" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 $as_echo "not found" >&6; } as_fn_error $? "cannot use diffheaders without TRE library" "$LINENO" 5 fi fi fi if test x"$enable_diffheaders" = x"yes" -a x"$tre_found" = x"yes" then $as_echo "#define USE_TRE 1" >>confdefs.h fi if test x"$tre_found" != x"no"; then USE_TRE_TRUE= USE_TRE_FALSE='#' else USE_TRE_TRUE='#' USE_TRE_FALSE= fi # # liblua # # Check whether --with-lua was given. if test "${with_lua+set}" = set; then : withval=$with_lua; luapath="$withval" else luapath="no" fi LIBLUA_INCDIRS="" LIBLUA_LIBDIRS="" LIBLUA_LIBS="" lua_found="no" if test \( x"$luapath" = x"auto" -o x"$luapath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBLUA" >&5 $as_echo_n "checking for LIBLUA... " >&6; } if test -n "$LIBLUA_CFLAGS"; then pkg_cv_LIBLUA_CFLAGS="$LIBLUA_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1\""; } >&5 ($PKG_CONFIG --exists --print-errors "lua5.1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBLUA_CFLAGS=`$PKG_CONFIG --cflags "lua5.1" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBLUA_LIBS"; then pkg_cv_LIBLUA_LIBS="$LIBLUA_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"lua5.1\""; } >&5 ($PKG_CONFIG --exists --print-errors "lua5.1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBLUA_LIBS=`$PKG_CONFIG --libs "lua5.1" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBLUA_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "lua5.1" 2>&1` else LIBLUA_PKG_ERRORS=`$PKG_CONFIG --print-errors "lua5.1" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBLUA_PKG_ERRORS" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for Lua not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for Lua not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for Lua not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for Lua not found, trying manual search..." >&2;} else LIBLUA_CFLAGS=$pkg_cv_LIBLUA_CFLAGS LIBLUA_LIBS=$pkg_cv_LIBLUA_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } lua_found="yes" LIBLUA_INCDIRS="$LIBLUA_CFLAGS" fi fi if test \( x"$luapath" = x"yes" -o x"$luapath" = x"auto" \) -a x"$lua_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Lua" >&5 $as_echo_n "checking for Lua... " >&6; } luadirs="/usr /usr/local" for d in $luadirs do if test -f $d/include/lua51/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBLUA_INCDIRS="-I$d/include/lua51" LIBLUA_LIBDIRS="-L$d/lib/lua51" LIBLUA_LIBS="-llua -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi $as_echo "#define USE_LUA 1" >>confdefs.h LUA_MANNOTICE="" lua_found="yes" break elif test -f $d/include/lua52/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBLUA_INCDIRS="-I$d/include/lua52" LIBLUA_LIBDIRS="-L$d/lib/lua52" LIBLUA_LIBS="-llua -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi $as_echo "#define USE_LUA 1" >>confdefs.h LUA_MANNOTICE="" lua_found="yes" break elif test -f $d/include/lua5.1/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBLUA_INCDIRS="-I$d/include/lua5.1" LIBLUA_LIBDIRS="-L$d/lib" LIBLUA_LIBS="-llua5.1 -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi $as_echo "#define USE_LUA 1" >>confdefs.h LUA_MANNOTICE="" lua_found="yes" break elif test -f $d/include/lua5.2/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBLUA_INCDIRS="-I$d/include/lua5.2" LIBLUA_LIBDIRS="-L$d/lib" LIBLUA_LIBS="-llua5.2 -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi $as_echo "#define USE_LUA 1" >>confdefs.h LUA_MANNOTICE="" lua_found="yes" break elif test -f $d/include/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } LIBLUA_INCDIRS="-I$d/include" LIBLUA_LIBDIRS="-L$d/lib" LIBLUA_LIBS="-llua -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi lua_found="yes" break fi done if test x"$LIBLUA_LIBS" = x"" then LIBLUA_INCDIRS="" LIBLUA_LIBDIRS="" LIBLUA_LIBS="" as_fn_error $? "not found" "$LINENO" 5 else lua_found="yes" fi fi if test x"$luapath" != x"yes" -a x"$luapath" != x"auto" -a x"$luapath" != x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Lua" >&5 $as_echo_n "checking for Lua... " >&6; } if test -f $luapath/include/lua51/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $luapath" >&5 $as_echo "$luapath" >&6; } LIBLUA_INCDIRS="-I$luapath/include/lua51" LIBLUA_LIBDIRS="-L$luapath/lib/lua51" LIBLUA_LIBS="-llua -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi lua_found="yes" elif test -f $luapath/include/lua52/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $luapath" >&5 $as_echo "$luapath" >&6; } LIBLUA_INCDIRS="-I$luapath/include/lua52" LIBLUA_LIBDIRS="-L$luapath/lib/lua52" LIBLUA_LIBS="-llua -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi lua_found="yes" elif test -f $luapath/include/lua5.1/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $luapath" >&5 $as_echo "$luapath" >&6; } LIBLUA_INCDIRS="-I$luapath/include/lua5.1" LIBLUA_LIBDIRS="-L$luapath/lib" LIBLUA_LIBS="-llua5.1 -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi lua_found="yes" elif test -f $luapath/include/lua5.2/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $luapath" >&5 $as_echo "$luapath" >&6; } LIBLUA_INCDIRS="-I$luapath/include/lua5.2" LIBLUA_LIBDIRS="-L$luapath/lib" LIBLUA_LIBS="-llua5.2 -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi lua_found="yes" elif test -f $luapath/include/lua.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $luapath" >&5 $as_echo "$luapath" >&6; } LIBLUA_INCDIRS="-I$luapath/include" LIBLUA_LIBDIRS="-L$luapath/lib" LIBLUA_LIBS="-llua -lm" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dlopen" >&5 $as_echo_n "checking for library containing dlopen... " >&6; } if ${ac_cv_search_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dlopen (); int main () { return dlopen (); ; return 0; } _ACEOF for ac_lib in '' dl; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dlopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dlopen+:} false; then : break fi done if ${ac_cv_search_dlopen+:} false; then : else ac_cv_search_dlopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dlopen" >&5 $as_echo "$ac_cv_search_dlopen" >&6; } ac_res=$ac_cv_search_dlopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" fi lua_found="yes" else as_fn_error $? "not found at $luapath" "$LINENO" 5 fi fi if test x"$lua_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$outer_CPPFLAGS $LIBLUA_INCDIRS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking Lua version" >&5 $as_echo_n "checking Lua version... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 # error Lua version 5.1 or later is required #endif int main() { return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else as_fn_error $? "Lua version 5.1 or later required" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CPPFLAGS="$saved_CPPFLAGS" $as_echo "#define USE_LUA 1" >>confdefs.h LUA_MANNOTICE="" else LUA_MANNOTICE="(Not enabled for this installation.)" fi if test x"$lua_found" = x"yes"; then LUA_TRUE= LUA_FALSE='#' else LUA_TRUE='#' LUA_FALSE= fi if test x"$enable_lua_only_signing" = x"yes" -a x"$lua_found" != x"yes" then as_fn_error $? "--enable-lua_only_signing requires Lua support" "$LINENO" 5 fi if test x"$enable_statsext" = x"yes" -a x"$lua_found" != x"yes" then as_fn_error $? "--enable-statsext requires Lua support" "$LINENO" 5 fi if test x"$enable_rbl" = x"yes" -a x"$lua_found" != x"yes" then as_fn_error $? "--enable-rbl requires Lua support" "$LINENO" 5 fi # Check whether --with-sql-backend was given. if test "${with_sql_backend+set}" = set; then : withval=$with_sql_backend; SQL_BACKEND="$withval" else SQL_BACKEND="mysql" fi cat >>confdefs.h <<_ACEOF #define SQL_BACKEND "$SQL_BACKEND" _ACEOF # # libodbx # # Check whether --with-odbx was given. if test "${with_odbx+set}" = set; then : withval=$with_odbx; odbxpath="$withval" else odbxpath="no" fi odbx_found="no" LIBODBX_CPPFLAGS="" LIBODBX_CFLAGS="" LIBODBX_LDFLAGS="" LIBODBX_LIBS="" if test \( x"$odbxpath" = x"auto" -o x"$odbxpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBODBX" >&5 $as_echo_n "checking for LIBODBX... " >&6; } if test -n "$LIBODBX_CFLAGS"; then pkg_cv_LIBODBX_CFLAGS="$LIBODBX_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"opendbx >= 1.3.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "opendbx >= 1.3.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBODBX_CFLAGS=`$PKG_CONFIG --cflags "opendbx >= 1.3.7" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBODBX_LIBS"; then pkg_cv_LIBODBX_LIBS="$LIBODBX_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"opendbx >= 1.3.7\""; } >&5 ($PKG_CONFIG --exists --print-errors "opendbx >= 1.3.7") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBODBX_LIBS=`$PKG_CONFIG --libs "opendbx >= 1.3.7" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBODBX_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "opendbx >= 1.3.7" 2>&1` else LIBODBX_PKG_ERRORS=`$PKG_CONFIG --print-errors "opendbx >= 1.3.7" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBODBX_PKG_ERRORS" >&5 odbx_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libodbx not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libodbx not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } odbx_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libodbx not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libodbx not found, trying manual search..." >&2;} else LIBODBX_CFLAGS=$pkg_cv_LIBODBX_CFLAGS LIBODBX_LIBS=$pkg_cv_LIBODBX_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } odbx_found="yes" fi fi if test x"$odbxpath" != x"no" -a x"$odbx_found" = x"no" then saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" if test x"$odbxpath" != x"auto" -a x"$odbxpath" != x"yes" then if test -f $odbxpath/include/odbx.h then LDFLAGS="$outer_LDFLAGS -L$odbxpath/lib" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing odbx_result_finish" >&5 $as_echo_n "checking for library containing odbx_result_finish... " >&6; } if ${ac_cv_search_odbx_result_finish+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char odbx_result_finish (); int main () { return odbx_result_finish (); ; return 0; } _ACEOF for ac_lib in '' opendbx; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -ldl $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_odbx_result_finish=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_odbx_result_finish+:} false; then : break fi done if ${ac_cv_search_odbx_result_finish+:} false; then : else ac_cv_search_odbx_result_finish=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_odbx_result_finish" >&5 $as_echo "$ac_cv_search_odbx_result_finish" >&6; } ac_res=$ac_cv_search_odbx_result_finish if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" odbx_found="yes" LIBODBX_CPPFLAGS="-I$odbxpath/include" LIBODBX_LDFLAGS="-L$odbxpath/lib" LIBODBX_LIBS="$LIBS" else as_fn_error $? "opendbx not at least v1.3.7 at $odbxpath" "$LINENO" 5 fi else as_fn_error $? "opendbx not found at $odbxpath" "$LINENO" 5 fi else odbxdirs="/usr /usr/local" for d in $odbxdirs do if test -f $d/include/odbx.h then LDFLAGS="$outer_LDFLAGS -L$d/lib" LIBS="$outer_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing odbx_result_finish" >&5 $as_echo_n "checking for library containing odbx_result_finish... " >&6; } if ${ac_cv_search_odbx_result_finish+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char odbx_result_finish (); int main () { return odbx_result_finish (); ; return 0; } _ACEOF for ac_lib in '' opendbx; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib -ldl $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_odbx_result_finish=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_odbx_result_finish+:} false; then : break fi done if ${ac_cv_search_odbx_result_finish+:} false; then : else ac_cv_search_odbx_result_finish=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_odbx_result_finish" >&5 $as_echo "$ac_cv_search_odbx_result_finish" >&6; } ac_res=$ac_cv_search_odbx_result_finish if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" odbxpath=$d odbx_found="yes" LIBODBX_CPPFLAGS="-I$d/include" LIBODBX_LDFLAGS="-L$d/lib" LIBODBX_LIBS="$LIBS" break else as_fn_error $? "opendbx not at least v1.3.7 at $d" "$LINENO" 5 fi fi done if test x"$odbx_found" != x"yes" then as_fn_error $? "opendbx not found" "$LINENO" 5 fi fi LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" fi if test x"$odbx_found" = x"yes" then $as_echo "#define USE_ODBX 1" >>confdefs.h else if test x"$enable_stats" = x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: opendbx is needed to import statistics into a SQL database - disabling opendkim-importstats and opendkim-spam" >&5 $as_echo "$as_me: WARNING: opendbx is needed to import statistics into a SQL database - disabling opendkim-importstats and opendkim-spam" >&2;} fi fi if test x"$odbx_found" = x"yes"; then USE_ODBX_TRUE= USE_ODBX_FALSE='#' else USE_ODBX_TRUE='#' USE_ODBX_FALSE= fi # # OpenLDAP # # Check whether --with-openldap was given. if test "${with_openldap+set}" = set; then : withval=$with_openldap; ldappath="$withval" else ldappath="no" fi ldap_found="no" OPENLDAP_CPPFLAGS="" OPENLDAP_LIBS="" if test \( x"$ldappath" = x"auto" -o x"$ldappath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OPENLDAP" >&5 $as_echo_n "checking for OPENLDAP... " >&6; } if test -n "$OPENLDAP_CFLAGS"; then pkg_cv_OPENLDAP_CFLAGS="$OPENLDAP_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openldap >= 2.0.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "openldap >= 2.0.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_OPENLDAP_CFLAGS=`$PKG_CONFIG --cflags "openldap >= 2.0.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$OPENLDAP_LIBS"; then pkg_cv_OPENLDAP_LIBS="$OPENLDAP_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"openldap >= 2.0.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "openldap >= 2.0.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_OPENLDAP_LIBS=`$PKG_CONFIG --libs "openldap >= 2.0.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then OPENLDAP_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "openldap >= 2.0.0" 2>&1` else OPENLDAP_PKG_ERRORS=`$PKG_CONFIG --print-errors "openldap >= 2.0.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$OPENLDAP_PKG_ERRORS" >&5 ldap_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for openldap not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for openldap not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } ldap_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for openldap not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for openldap not found, trying manual search..." >&2;} else OPENLDAP_CFLAGS=$pkg_cv_OPENLDAP_CFLAGS OPENLDAP_LIBS=$pkg_cv_OPENLDAP_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } ldap_found="yes" OPENLDAP_CPPFLAGS="$OPENLDAP_CFLAGS" fi fi if test x"$ldappath" != x"no" -a x"$ldap_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for OpenLDAP" >&5 $as_echo_n "checking for OpenLDAP... " >&6; } if test x"$ldappath" != x"auto" -a x"$ldappath" != x"yes" then if test -f $ldappath/include/ldap.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ldappath" >&5 $as_echo "$ldappath" >&6; } ldap_found="yes" OPENLDAP_CPPFLAGS="-I$ldappath/include" OPENLDAP_LIBS="-L$ldappath/lib -lldap -llber" else as_fn_error $? "not found at $ldappath" "$LINENO" 5 fi else ldapdirs="/usr /usr/local" for d in $ldapdirs do if test -f $d/include/ldap.h then ldappath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } ldap_found="yes" OPENLDAP_CPPFLAGS="-I$ldappath/include" OPENLDAP_LIBS="-L$ldappath/lib -lldap -llber" break fi done fi if test x"$ldap_found" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x"$ldap_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$outer_CPPFLAGS $OPENLDAP_CPPFLAGS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking OpenLDAP version" >&5 $as_echo_n "checking OpenLDAP version... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #if !defined(LDAP_API_VERSION) || LDAP_API_VERSION < 2004 # error OpenLDAP version 2.1.3 or later is required #endif int main() { return 0; } _ACEOF if ac_fn_c_try_compile "$LINENO"; then : { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } else as_fn_error $? "OpenLDAP version 2.1.3 or later required" "$LINENO" 5 fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext CPPFLAGS="$saved_CPPFLAGS" $as_echo "#define USE_LDAP 1" >>confdefs.h fi if test x"$ldap_found" = x"yes"; then USE_LDAP_TRUE= USE_LDAP_FALSE='#' else USE_LDAP_TRUE='#' USE_LDAP_FALSE= fi # # SASL # # Check whether --with-sasl was given. if test "${with_sasl+set}" = set; then : withval=$with_sasl; saslpath="$withval" else saslpath="auto" fi if test x"$ldap_found" != x"yes" then # disable sasl if we don't have ldap saslpath="no" fi sasl_found="no" if test \( x"$saslpath" = x"auto" -o x"$saslpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SASL" >&5 $as_echo_n "checking for SASL... " >&6; } if test -n "$SASL_CFLAGS"; then pkg_cv_SASL_CFLAGS="$SASL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cyrussasl >= 2.1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "cyrussasl >= 2.1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SASL_CFLAGS=`$PKG_CONFIG --cflags "cyrussasl >= 2.1.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$SASL_LIBS"; then pkg_cv_SASL_LIBS="$SASL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"cyrussasl >= 2.1.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "cyrussasl >= 2.1.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_SASL_LIBS=`$PKG_CONFIG --libs "cyrussasl >= 2.1.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then SASL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "cyrussasl >= 2.1.0" 2>&1` else SASL_PKG_ERRORS=`$PKG_CONFIG --print-errors "cyrussasl >= 2.1.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$SASL_PKG_ERRORS" >&5 sasl_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for cyrussasl not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for cyrussasl not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } sasl_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for cyrussasl not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for cyrussasl not found, trying manual search..." >&2;} else SASL_CFLAGS=$pkg_cv_SASL_CFLAGS SASL_LIBS=$pkg_cv_SASL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } sasl_found="yes" SASL_CPPFLAGS="$SASL_CFLAGS" fi fi if test x"$saslpath" != x"no" -a x"$sasl_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SASL" >&5 $as_echo_n "checking for SASL... " >&6; } if test x"$saslpath" != x"auto" -a x"$saslpath" != x"yes" then if test -f $saslpath/include/sasl/sasl.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $saslpath" >&5 $as_echo "$saslpath" >&6; } sasl_found="yes" SASL_CPPFLAGS="-I$saslpath/include" else as_fn_error $? "not found at $saslpath" "$LINENO" 5 fi else sasldirs="/usr /usr/local" for d in $sasldirs do if test -f $d/include/sasl/sasl.h then saslpath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } sasl_found="yes" SASL_CPPFLAGS="-I$saslpath/include" break fi done fi if test x"$sasl_found" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x"$sasl_found" = x"yes" then $as_echo "#define USE_SASL 1" >>confdefs.h fi if test x"$sasl_found" = x"yes"; then USE_SASL_TRUE= USE_SASL_FALSE='#' else USE_SASL_TRUE='#' USE_SASL_FALSE= fi # # libmdb # # Check whether --with-lmdb was given. if test "${with_lmdb+set}" = set; then : withval=$with_lmdb; mdbpath="$withval" else mdbpath="no" fi mdb_found="no" LIBMDB_CPPFLAGS="" LIBMDB_LIBS="" if test x"$mdbpath" != x"no" -a x"$mdb_found" = x"no" then saved_ldflags="$LDFLAGS" saved_cflags="$CFLAGS" CFLAGS="$outer_CFLAGS -pthread" if test x"$mdbpath" != x"auto" -a x"$mdbpath" != x"yes" then if test -f $mdbpath/include/lmdb.h then LDFLAGS="$outer_LDFLAGS -L$mdbpath/lib $STRL_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mdb_env_open in -llmdb" >&5 $as_echo_n "checking for mdb_env_open in -llmdb... " >&6; } if ${ac_cv_lib_lmdb_mdb_env_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llmdb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mdb_env_open (); int main () { return mdb_env_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lmdb_mdb_env_open=yes else ac_cv_lib_lmdb_mdb_env_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmdb_mdb_env_open" >&5 $as_echo "$ac_cv_lib_lmdb_mdb_env_open" >&6; } if test "x$ac_cv_lib_lmdb_mdb_env_open" = xyes; then : mdb_found="yes" LIBMDB_CPPFLAGS="-I$mdbpath/include" LIBMDB_LIBS="-L$mdbpath/lib -llmdb" else as_fn_error $? "lmdb not valid at $mdbpath" "$LINENO" 5 fi else as_fn_error $? "lmdb not found at $mdbpath" "$LINENO" 5 fi else mdbdirs="/usr /usr/local" for d in $mdbdirs do if test -f $d/include/lmdb.h then LDFLAGS="$outer_LDFLAGS -L$d/lib $STRL_LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for mdb_env_open in -llmdb" >&5 $as_echo_n "checking for mdb_env_open in -llmdb... " >&6; } if ${ac_cv_lib_lmdb_mdb_env_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-llmdb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char mdb_env_open (); int main () { return mdb_env_open (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_lmdb_mdb_env_open=yes else ac_cv_lib_lmdb_mdb_env_open=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lmdb_mdb_env_open" >&5 $as_echo "$ac_cv_lib_lmdb_mdb_env_open" >&6; } if test "x$ac_cv_lib_lmdb_mdb_env_open" = xyes; then : mdbpath=$d mdb_found="yes" LIBMDB_CPPFLAGS="-I$mdbpath/include" LIBMDB_LIBS="-L$mdbpath/lib -llmdb" break fi fi done if test x"$mdb_found" != x"yes" then as_fn_error $? "lmdb not found" "$LINENO" 5 fi fi LDFLAGS="$saved_ldflags" CFLAGS="$saved_cflags" fi if test x"$mdb_found" = x"yes" then $as_echo "#define USE_MDB 1" >>confdefs.h fi if test x"$mdb_found" = x"yes"; then USE_MDB_TRUE= USE_MDB_FALSE='#' else USE_MDB_TRUE='#' USE_MDB_FALSE= fi # # # libcurl, required by reputation # # Check whether --with-libcurl was given. if test "${with_libcurl+set}" = set; then : withval=$with_libcurl; curlpath="$withval" else curlpath="auto" fi CURL_CPPFLAGS="" CURL_LDFLAGS="" CURL_LIBS="" if test x"$enable_reputation" != x"yes" -a \ x"$curlpath" = x"auto" then curlpath="no" fi curl_found="no" if test \( x"$curlpath" = x"auto" -o x"$curlpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5 $as_echo_n "checking for CURL... " >&6; } if test -n "$CURL_CFLAGS"; then pkg_cv_CURL_CFLAGS="$CURL_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl >= 7.12.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libcurl >= 7.12.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CURL_CFLAGS=`$PKG_CONFIG --cflags "libcurl >= 7.12.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$CURL_LIBS"; then pkg_cv_CURL_LIBS="$CURL_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libcurl >= 7.12.0\""; } >&5 ($PKG_CONFIG --exists --print-errors "libcurl >= 7.12.0") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_CURL_LIBS=`$PKG_CONFIG --libs "libcurl >= 7.12.0" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then CURL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libcurl >= 7.12.0" 2>&1` else CURL_PKG_ERRORS=`$PKG_CONFIG --print-errors "libcurl >= 7.12.0" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$CURL_PKG_ERRORS" >&5 curl_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for curl not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for curl not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } curl_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for curl not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for curl not found, trying manual search..." >&2;} else CURL_CFLAGS=$pkg_cv_CURL_CFLAGS CURL_LIBS=$pkg_cv_CURL_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } curl_found="yes" CURL_CPPFLAGS="$CURL_CFLAGS" fi fi if test x"$curlpath" != x"no" -a x"$curl_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CURL" >&5 $as_echo_n "checking for CURL... " >&6; } if test x"$curlpath" != x"auto" -a x"$curlpath" != x"yes" then if test -f $curlpath/include/curl/curl.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $curlpath" >&5 $as_echo "$curlpath" >&6; } curl_found="yes" CURL_CPPFLAGS="-I$curlpath/include" CURL_LDFLAGS="$outer_LDFLAGS -L$curlpath/lib" CURL_LIBS="-lcurl" else as_fn_error $? "not found at $curlpath" "$LINENO" 5 fi else curldirs="/usr /usr/local" for d in $curldirs do if test -f $d/include/curl/curl.h then curlpath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } curl_found="yes" CURL_CPPFLAGS="-I$curlpath/include" CURL_LDFLAGS="$outer_LDFLAGS -L$curlpath/lib" CURL_LIBS="-lcurl" break fi done fi if test x"$curl_found" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x"$curl_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $CURL_CPPFLAGS" LDFLAGS="$LDFLAGS $CURL_LDFLAGS" LIBS="$LIBS $CURL_LIBS" ac_fn_c_check_func "$LINENO" "curl_easy_strerror" "ac_cv_func_curl_easy_strerror" if test "x$ac_cv_func_curl_easy_strerror" = xyes; then : $as_echo "#define HAVE_CURL_EASY_STRERROR 1" >>confdefs.h fi CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" LIBCURL_MANNOTICE="" else LIBCURL_MANNOTICE="(Not enabled for this installation.)" fi if test x"$enable_reputation" = x"yes" -a \ x"$curl_found" != x"yes" then as_fn_error $? "reputation requires curl" "$LINENO" 5 fi # # reputation requires libjansson # # Check whether --with-libjansson was given. if test "${with_libjansson+set}" = set; then : withval=$with_libjansson; janssonpath="$withval" else janssonpath="auto" fi LIBJANSSON_CPPFLAGS="" LIBJANSSON_LDFLAGS="" LIBJANSSON_LIBS="" # if reputation is disabled, we don't need it if test x"$enable_reputation" != x"yes" -a \ x"$janssonpath" = x"auto" then janssonpath="no" fi jansson_found="no" if test \( x"$janssonpath" = x"auto" -o x"$janssonpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBJANSSON" >&5 $as_echo_n "checking for LIBJANSSON... " >&6; } if test -n "$LIBJANSSON_CFLAGS"; then pkg_cv_LIBJANSSON_CFLAGS="$LIBJANSSON_CFLAGS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.2.1\""; } >&5 ($PKG_CONFIG --exists --print-errors "jansson >= 2.2.1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBJANSSON_CFLAGS=`$PKG_CONFIG --cflags "jansson >= 2.2.1" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test -n "$LIBJANSSON_LIBS"; then pkg_cv_LIBJANSSON_LIBS="$LIBJANSSON_LIBS" elif test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG" && \ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"jansson >= 2.2.1\""; } >&5 ($PKG_CONFIG --exists --print-errors "jansson >= 2.2.1") 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then pkg_cv_LIBJANSSON_LIBS=`$PKG_CONFIG --libs "jansson >= 2.2.1" 2>/dev/null` else pkg_failed=yes fi else pkg_failed=untried fi if test $pkg_failed = yes; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi if test $_pkg_short_errors_supported = yes; then LIBJANSSON_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "jansson >= 2.2.1" 2>&1` else LIBJANSSON_PKG_ERRORS=`$PKG_CONFIG --print-errors "jansson >= 2.2.1" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$LIBJANSSON_PKG_ERRORS" >&5 jansson_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libjansson not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libjansson not found, trying manual search..." >&2;} elif test $pkg_failed = untried; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } jansson_found="no" { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pkg-config for libjansson not found, trying manual search..." >&5 $as_echo "$as_me: WARNING: pkg-config for libjansson not found, trying manual search..." >&2;} else LIBJANSSON_CFLAGS=$pkg_cv_LIBJANSSON_CFLAGS LIBJANSSON_LIBS=$pkg_cv_LIBJANSSON_LIBS { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } jansson_found="yes" LIBJANSSON_CPPFLAGS="$LIBJANSSON_CFLAGS" LIBJANSSON_LIBS="$LIBJANSSON_LIBS" fi fi if test x"$janssonpath" != x"no" -a x"$jansson_found" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libjansson" >&5 $as_echo_n "checking for libjansson... " >&6; } if test x"$janssonpath" != x"auto" -a x"$janssonpath" != x"yes" then if test -f $janssonpath/include/jansson.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $janssonpath" >&5 $as_echo "$janssonpath" >&6; } jansson_found="yes" LIBJANSSON_CPPFLAGS="-I$janssonpath/include" LIBJANSSON_LDFLAGS="-L$janssonpath/lib" LIBJANSSON_LIBS="-ljansson" else as_fn_error $? "not found at $janssonpath" "$LINENO" 5 fi else janssondirs="/usr /usr/local" for d in $janssondirs do if test -f $d/include/jansson.h then janssonpath=$d { $as_echo "$as_me:${as_lineno-$LINENO}: result: $d" >&5 $as_echo "$d" >&6; } jansson_found="yes" LIBJANSSON_CPPFLAGS="-I$janssonpath/include" LIBJANSSON_LDFLAGS="-L$janssonpath/lib" LIBJANSSON_LIBS="-ljansson" break fi done fi if test x"$jansson_found" != x"yes" then { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi fi if test x"$LIBJANSSON_LIBS" != x""; then JANSSON_TRUE= JANSSON_FALSE='#' else JANSSON_TRUE='#' JANSSON_FALSE= fi if test x"$enable_reputation" = x"yes" -a \ x"$jansson_found" != x"yes" then as_fn_error $? "reputation requires libjansson" "$LINENO" 5 fi if test x"$jansson_found" == x"yes" then $as_echo "#define USE_JANSSON 1" >>confdefs.h fi # # libdb # # Check whether --with-db-incdir was given. if test "${with_db_incdir+set}" = set; then : withval=$with_db_incdir; bdb_incdir="$withval" else bdb_incdir="" fi # Check whether --with-db-libdir was given. if test "${with_db_libdir+set}" = set; then : withval=$with_db_libdir; bdb_libdir="$withval" else bdb_libdir="" fi # Check whether --with-db-lib was given. if test "${with_db_lib+set}" = set; then : withval=$with_db_lib; bdb_lib="$withval" else bdb_lib="db" fi # Check whether --with-db was given. if test "${with_db+set}" = set; then : withval=$with_db; bdb="$withval" else bdb="auto" fi LIBDB_INCDIRS="" LIBDB_LIBDIRS="" LIBDB_LIBS="" # was --with-db given with "yes" or a path? bdbrequested="no" if test x"$bdb" != x"no" -a x"$bdb" != x"auto" then bdbrequested="yes" fi if test x"$bdb_incdir" != x"" -o x"$bdb_libdir" != x"" -o x"$bdb_lib" != x"db" then bdbrequested="yes" fi rep_needs_bdb="no" if test x"$enable_reputation" = x"yes" -a x"$mdb_found" = x"no" then rep_needs_bdb="yes" fi if test x"$enable_popauth" = x"yes" -o \ x"$rep_needs_bdb" = x"yes" -o \ x"$enable_ldap_caching" = x"yes" -o \ x"$bdbrequested" = x"yes"; then USE_DB_OPENDKIM_TRUE= USE_DB_OPENDKIM_FALSE='#' else USE_DB_OPENDKIM_TRUE='#' USE_DB_OPENDKIM_FALSE= fi if test x"$enable_query_cache" = x"yes"; then USE_DB_LIBOPENDKIM_TRUE= USE_DB_LIBOPENDKIM_FALSE='#' else USE_DB_LIBOPENDKIM_TRUE='#' USE_DB_LIBOPENDKIM_FALSE= fi # Is DB required based on --enables? if test x"$USE_DB_OPENDKIM_TRUE" = x"" -o \ x"$USE_DB_LIBOPENDKIM_TRUE" = x"" then bdbrequired="yes" else bdbrequired="no" fi # If --with-db wasn't specified and the --enables demand it, force "yes" if test x"$bdb" = x"auto" then if test x"$bdbrequired" = x"yes" then bdb="yes" else bdb="no" fi fi if test x"$bdb" != x"yes" -a x"$bdb" != x"no" then bdb_incdir=$bdb/include bdb_libdir=$bdb/lib bdb="yes" fi if test x"$bdb" = x"yes" then bdbdirs="/usr/local/BerkeleyDB /usr/local /usr" libdbfound="no" # look for db.h { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BerkeleyDB db.h" >&5 $as_echo_n "checking for BerkeleyDB db.h... " >&6; } if test x"$bdb_incdir" = x"" then for d in $bdbdirs do if test -f $d/include/db.h then bdb_incdir=$d/include { $as_echo "$as_me:${as_lineno-$LINENO}: result: $bdb_incdir" >&5 $as_echo "$bdb_incdir" >&6; } break fi done if test x"$bdb_incdir" = x"" then as_fn_error $? "not found" "$LINENO" 5 fi elif ! test -f $bdb_incdir/db.h then as_fn_error $? "not found in $bdb_incdir" "$LINENO" 5 else { $as_echo "$as_me:${as_lineno-$LINENO}: result: $bdb_incdir" >&5 $as_echo "$bdb_incdir" >&6; } fi # See if we can find a library by looking for db_create(), then # db_open(), then dbopen(). # # This can cause compilation problems if for example a db.h # and a libdb are found that aren't the same version, but it's # worth a shot in general. if test x"$bdb_libdir" = x"" then for d in $bdbdirs do saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LIBS="$LIBS" LDFLAGS="$LDFLAGS -L$d/lib" CPPFLAGS="$CPPFLAGS -I$bdb_incdir" LIBS="$outer_LIBS" if test x"$libdbfound" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing db_create" >&5 $as_echo_n "checking for library containing db_create... " >&6; } if ${ac_cv_search_db_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char db_create (); int main () { return db_create (); ; return 0; } _ACEOF for ac_lib in '' $bdb_lib; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_db_create=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_db_create+:} false; then : break fi done if ${ac_cv_search_db_create+:} false; then : else ac_cv_search_db_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_db_create" >&5 $as_echo "$ac_cv_search_db_create" >&6; } ac_res=$ac_cv_search_db_create if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libdbfound="yes" fi bdb_libdir=$d/lib fi if test x"$libdbfound" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing db_open" >&5 $as_echo_n "checking for library containing db_open... " >&6; } if ${ac_cv_search_db_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char db_open (); int main () { return db_open (); ; return 0; } _ACEOF for ac_lib in '' $bdb_lib; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_db_open=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_db_open+:} false; then : break fi done if ${ac_cv_search_db_open+:} false; then : else ac_cv_search_db_open=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_db_open" >&5 $as_echo "$ac_cv_search_db_open" >&6; } ac_res=$ac_cv_search_db_open if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libdbfound="yes" fi bdb_libdir=$d/lib fi if test x"$libdbfound" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dbopen" >&5 $as_echo_n "checking for library containing dbopen... " >&6; } if ${ac_cv_search_dbopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dbopen (); int main () { return dbopen (); ; return 0; } _ACEOF for ac_lib in '' $bdb_lib; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dbopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dbopen+:} false; then : break fi done if ${ac_cv_search_dbopen+:} false; then : else ac_cv_search_dbopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dbopen" >&5 $as_echo "$ac_cv_search_dbopen" >&6; } ac_res=$ac_cv_search_dbopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libdbfound="yes" fi bdb_libdir=$d/lib fi LDFLAGS="$saved_LDFLAGS" CPPFLAGS="$saved_CPPFLAGS" LIBS="$saved_LIBS" done else saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LIBS="$LIBS" LDFLAGS="$LDFLAGS -L$bdb_libdir" CPPFLAGS="$CPPFLAGS -I$bdb_incdir" LIBS="$outer_LIBS" if test x"$libdbfound" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing db_create" >&5 $as_echo_n "checking for library containing db_create... " >&6; } if ${ac_cv_search_db_create+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char db_create (); int main () { return db_create (); ; return 0; } _ACEOF for ac_lib in '' $bdb_lib; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_db_create=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_db_create+:} false; then : break fi done if ${ac_cv_search_db_create+:} false; then : else ac_cv_search_db_create=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_db_create" >&5 $as_echo "$ac_cv_search_db_create" >&6; } ac_res=$ac_cv_search_db_create if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libdbfound="yes" fi fi if test x"$libdbfound" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing db_open" >&5 $as_echo_n "checking for library containing db_open... " >&6; } if ${ac_cv_search_db_open+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char db_open (); int main () { return db_open (); ; return 0; } _ACEOF for ac_lib in '' $bdb_lib; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_db_open=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_db_open+:} false; then : break fi done if ${ac_cv_search_db_open+:} false; then : else ac_cv_search_db_open=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_db_open" >&5 $as_echo "$ac_cv_search_db_open" >&6; } ac_res=$ac_cv_search_db_open if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libdbfound="yes" fi fi if test x"$libdbfound" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing dbopen" >&5 $as_echo_n "checking for library containing dbopen... " >&6; } if ${ac_cv_search_dbopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char dbopen (); int main () { return dbopen (); ; return 0; } _ACEOF for ac_lib in '' $bdb_lib; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_dbopen=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_dbopen+:} false; then : break fi done if ${ac_cv_search_dbopen+:} false; then : else ac_cv_search_dbopen=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_dbopen" >&5 $as_echo "$ac_cv_search_dbopen" >&6; } ac_res=$ac_cv_search_dbopen if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" libdbfound="yes" fi fi LDFLAGS="$saved_LDFLAGS" CPPFLAGS="$saved_CPPFLAGS" LIBS="$saved_LIBS" fi if test x"$libdbfound" = x"no" then as_fn_error $? "cannot find db_create, db_open or dbopen" "$LINENO" 5 fi if test x"$bdb_incdir" != x"" then LIBDB_INCDIRS="-I$bdb_incdir" fi if test x"$bdb_libdir" != x"" then LIBDB_LIBDIRS="-L$bdb_libdir" LIBDB_LIBS="-l$bdb_lib" fi $as_echo "#define USE_DB 1" >>confdefs.h elif test x"$bdb" = x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BerkeleyDB" >&5 $as_echo_n "checking for BerkeleyDB... " >&6; } if test x"$bdbrequired" = x"yes" then as_fn_error $? "disabled but required by requested features" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: not required or disabled" >&5 $as_echo "not required or disabled" >&6; } LIBDB_INCDIRS="" LIBDB_LIBDIRS="" LIBDB_LIBS="" fi if test x"$unboundpath" != x"no" -a x"$bdbrequired" = x"yes" then saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $LIBDB_LIBDIRS $LIBUNBOUND_LIBDIRS" CPPFLAGS="$CPPFLAGS $LIBDB_INCDIRS $LIBUNBOUND_INCDIRS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for log_file in -ldb" >&5 $as_echo_n "checking for log_file in -ldb... " >&6; } if ${ac_cv_lib_db_log_file+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-ldb $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char log_file (); int main () { return log_file (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_db_log_file=yes else ac_cv_lib_db_log_file=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_db_log_file" >&5 $as_echo "$ac_cv_lib_db_log_file" >&6; } if test "x$ac_cv_lib_db_log_file" = xyes; then : { $as_echo "$as_me:${as_lineno-$LINENO}: checking for log_file in -lunbound" >&5 $as_echo_n "checking for log_file in -lunbound... " >&6; } if ${ac_cv_lib_unbound_log_file+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS LIBS="-lunbound $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char log_file (); int main () { return log_file (); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : ac_cv_lib_unbound_log_file=yes else ac_cv_lib_unbound_log_file=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_unbound_log_file" >&5 $as_echo "$ac_cv_lib_unbound_log_file" >&6; } if test "x$ac_cv_lib_unbound_log_file" = xyes; then : as_fn_error $? "Cannot enable feature requiring BerkeleyDB with libunbound - both have log_file defined. Please use newer BerkeleyDB version" "$LINENO" 5 fi fi LDFLAGS="$saved_LDFLAGS" CPPFLAGS="$saved_CPPFLAGS" fi LIBOPENDKIM_LIBS="$LIBCRYPTO_LIBS $LIBTRE_LIBS $LIBRESOLV" # This (below) is just for the pkg-config file opendkim.pc.in LIBOPENDKIM_LIBS_PKG="$LIBOPENDKIM_LIBS" LIBOPENDKIM_INC="$LIBCRYPTO_CPPFLAGS $LIBCRYPTO_CFLAGS $LIBTRE_CPPFLAGS" if test x"$USE_DB_LIBOPENDKIM_TRUE" = x"" then LIBOPENDKIM_INC="$LIBOPENDKIM_INC $LIBDB_INCDIRS" LIBOPENDKIM_LIBS_PKG="$LIBOPENDKIM_LIBS_PKG $LIBDB_LIBS" LIBOPENDKIM_LIBS="$LIBOPENDKIM_LIBS $LIBDB_LIBS" fi cat >>confdefs.h <<_ACEOF #define LIBOPENDKIM_FEATURE_STRING "$LIBOPENDKIM_FEATURE_STRING" _ACEOF # # setup for testing # # Check whether --enable-live-testing was given. if test "${enable_live_testing+set}" = set; then : enableval=$enable_live_testing; live_tests="$enable_live_testing" else live_tests="yes" fi if test x"$live_tests" = x"yes"; then LIVE_TESTS_TRUE= LIVE_TESTS_FALSE='#' else LIVE_TESTS_TRUE='#' LIVE_TESTS_FALSE= fi # # specify test socket # # Check whether --with-test-socket was given. if test "${with_test_socket+set}" = set; then : withval=$with_test_socket; testsocket="$withval" else testsocket="" fi if test x"$testsocket" != x""; then TEST_SOCKET_TRUE= TEST_SOCKET_FALSE='#' else TEST_SOCKET_TRUE='#' TEST_SOCKET_FALSE= fi if test x"$testsocket" != x"" then TESTSOCKET=$testsocket fi # # Platform Specific Configuration # case "$host" in *-darwin*) CPPFLAGS="$CPPFLAGS -DBIND_8_COMPAT -DDARWIN" if test x"$unboundpath" = x"no" then as_fn_error $? "\"unbound required on Darwin\"" "$LINENO" 5 fi ;; esac # # Determine domainname for sample configs # # Check whether --with-domain was given. if test "${with_domain+set}" = set; then : withval=$with_domain; DOMAIN="$withval" else # Extract the first word of "domainname", so it can be a program name with args. set dummy domainname; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } if ${ac_cv_path_domainname+:} false; then : $as_echo_n "(cached) " >&6 else case $domainname in [\\/]* | ?:[\\/]*) ac_cv_path_domainname="$domainname" # Let the user override the test with a path. ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_path_domainname="$as_dir/$ac_word$ac_exec_ext" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi done done IFS=$as_save_IFS ;; esac fi domainname=$ac_cv_path_domainname if test -n "$domainname"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $domainname" >&5 $as_echo "$domainname" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi if test x"$domainname" != x""; then : DOMAIN=`$domainname` fi if test x"$DOMAIN" = x"" -o x"$DOMAIN" = x"(none)" ; then : DOMAIN=example.com fi fi # Check whether --with-erlang was given. if test "${with_erlang+set}" = set; then : withval=$with_erlang; erlpath="$withval" else erlpath="no" fi LIBERL_INCDIRS="" LIBERL_LIBDIRS="" LIBERL_LIBS="" erl_found="no" if test \( x"$erlpath" = x"yes" -o x"$erlpath" = x"auto" \) then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Erlang" >&5 $as_echo_n "checking for Erlang... " >&6; } b=`erl -noshell -eval 'io:format("~s~n", [code:lib_dir()]).' -s erlang halt` erlbase=`ls -d $b/erl_interface-* | tail -n1` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $erlbase" >&5 $as_echo "$erlbase" >&6; } LIBERL_INCDIRS="-I$erlbase/include" LIBERL_LIBDIRS="-L$erlbase/lib" LIBERL_LIBS="-pthread -lerl_interface -lei" $as_echo "#define USE_ERLANG 1" >>confdefs.h erl_found="yes" fi if test x"$erlpath" != x"yes" -a x"$erlpath" != x"auto" -a x"$erlpath" != x"no" then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Erlang" >&5 $as_echo_n "checking for Erlang... " >&6; } if test -f $erlpath/include/ei.h then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $erlpath" >&5 $as_echo "$erlpath" >&6; } LIBERL_INCDIRS="-I$erlpath/include" LIBERL_LIBDIRS="-L$erlpath/lib" LIBERL_LIBS="-pthread -lerl_interface -lei" erl_found="yes" else as_fn_error $? "not found at $erlpath" "$LINENO" 5 fi fi if test x"$erl_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$outer_CPPFLAGS $LIBERL_INCDIRS" $as_echo "#define USE_ERLANG 1" >>confdefs.h LIBERL_MANNOTICE="" else LIBERL_MANNOTICE="(Not enabled for this installation.)" fi if test x"$erl_found" = x"yes"; then ERLANG_TRUE= ERLANG_FALSE='#' else ERLANG_TRUE='#' ERLANG_FALSE= fi # # final command line tweaks # CPPFLAGS="$CPPFLAGS -DCONFIG_BASE=\\\"$sysconfdir\\\"" test "x$prefix" = xNONE && prefix=$ac_default_prefix SYSCONFDIR=`eval echo "$sysconfdir"` # # for contrib/spec/opendkim.spec.in # installbin="no" specconfig="" specrequires="" specbuildrequires="" if test x"$enable_reputation" = x"yes" then specconfig="$specconfig --enable-reputation" specrequires="$specrequires libcurl" specbuildrequires="$specbuildrequires libcurl-devel jansson-devel" fi if test x"$enable_stats" = x"yes" then specconfig="$specconfig --enable-stats --with-odbx" specrequires="$specrequires libdb opendbx" specbuildrequires="$specbuildrequires libdb-devel opendbx-devel" fi if test x"$jansson_found" = x"yes" then # autobuild installbin="yes" specconfig="$specconfig --with-libjansson=$janssonpath" fi # opendkim-spam if test x"$enable_stats" = x"yes" -a x"$odbx_found" = x"yes" then installbin="yes" specconfig="$specconfig --enable-stats --with-odbx=$odbxpath" fi # miltertest if test x"$lua_found" = x"yes" then installbin="yes" specconfig="$specconfig --with-lua=$luapath" specrequries="$specrequires lua" specbuildrequries="$specbuildrequires lua-devel" fi SPECBINDIR="" if test x"$installbin" = x"yes" then SPECBINDIR="%{_bindir}/*" fi SPECCONFIGURE="$specconfig" if test x"$specrequires" = x"" then SPECREQUIRES="" else SPECREQUIRES="Requires:$specrequires" fi if test x"$specbuildrequires" = x"" then SPECBUILDREQUIRES="" else SPECBUILDREQUIRES="BuildRequires:$specbuildrequires" fi # # Finish up # ac_config_files="$ac_config_files Makefile docs/Makefile autobuild/Makefile contrib/Makefile contrib/convert/Makefile contrib/docs/Makefile contrib/init/Makefile contrib/init/generic/Makefile contrib/init/redhat/Makefile contrib/init/redhat/opendkim contrib/init/redhat/opendkim-default-keygen contrib/init/solaris/Makefile contrib/ldap/Makefile contrib/lua/Makefile contrib/patches/Makefile contrib/repute/Makefile contrib/spec/Makefile contrib/spec/opendkim.spec contrib/stats/Makefile contrib/systemd/Makefile contrib/systemd/opendkim.service libopendkim/opendkim.pc libopendkim/Makefile libopendkim/docs/Makefile libopendkim/tests/Makefile librbl/rbl.pc librbl/Makefile libut/ut.pc libut/Makefile libvbr/vbr.pc libvbr/Makefile miltertest/Makefile opendkim/Makefile opendkim/opendkim.8 opendkim/opendkim-genkey opendkim/opendkim-genkey.8 opendkim/opendkim-genzone.8 opendkim/opendkim-lua.3 opendkim/opendkim-testkey.8 opendkim/opendkim-stats.8 opendkim/opendkim-testmsg.8 opendkim/opendkim.conf.5 opendkim/opendkim.conf.simple opendkim/opendkim.conf.simple-verify opendkim/opendkim-atpszone.8 opendkim/opendkim-spam.1 opendkim/tests/Makefile stats/Makefile stats/opendkim-importstats.8 stats/opendkim-expire stats/opendkim-expire.8 stats/opendkim-gengraphs stats/opendkim-gengraphs.8 stats/opendkim-genstats stats/opendkim-genstats.8 stats/opendkim-reportstats reprrd/Makefile reprrd/opendkim-reprrdimport reprrd/opendkim-reprrdimport.8 reprrd/reprrd.pc reputation/Makefile reputation/opendkim-genrates reputation/opendkim-genrates.8 reputation/opendkim-modtotals reputation/opendkim-modtotals.8 reputation/opendkim-rephistory reputation/opendkim-rephistory.8 reputation/repute.pc" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure # scripts and configure runs, see configure's option --config-cache. # It is not useful on other systems. If it contains results you don't # want to keep, you may remove or edit it. # # config.status only pays attention to the cache file if you give it # the --recheck option to rerun configure. # # `ac_cv_env_foo' variables (set or unset) will be overridden when # loading this file, other *unset* `ac_cv_foo' will be assigned the # following values. _ACEOF # The following way of writing the cache mishandles newlines in values, # but we know of no workaround that is simple, portable, and efficient. # So, we kill variables containing newlines. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. ( for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do eval ac_val=\$$ac_var case $ac_val in #( *${as_nl}*) case $ac_var in #( *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; esac case $ac_var in #( _ | IFS | as_nl) ;; #( BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( *) { eval $ac_var=; unset $ac_var;} ;; esac ;; esac done (set) 2>&1 | case $as_nl`(ac_space=' '; set) 2>&1` in #( *${as_nl}ac_space=\ *) # `set' does not quote correctly, so add quotes: double-quote # substitution turns \\\\ into \\, and sed turns \\ into \. sed -n \ "s/'/'\\\\''/g; s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" ;; #( *) # `set' quotes correctly as required by POSIX, so do not add quotes. sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" ;; esac | sort ) | sed ' /^ac_cv_env_/b end t clear :clear s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ t end s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} if test ! -f "$cache_file" || test -h "$cache_file"; then cat confcache >"$cache_file" else case $cache_file in #( */* | ?:*) mv -f confcache "$cache_file"$$ && mv -f "$cache_file"$$ "$cache_file" ;; #( *) mv -f confcache "$cache_file" ;; esac fi fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} fi fi rm -f confcache test "x$prefix" = xNONE && prefix=$ac_default_prefix # Let make expand exec_prefix. test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' ac_i=`$as_echo "$ac_i" | sed "$ac_script"` # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR # will be set to the directory where LIBOBJS objects are built. as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' done LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs { $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 $as_echo_n "checking that generated files are newer than configure... " >&6; } if test -n "$am_sleep_pid"; then # Hide warnings about reused PIDs. wait $am_sleep_pid 2>/dev/null fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 $as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' else am__EXEEXT_TRUE='#' am__EXEEXT_FALSE= fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then as_fn_error $? "conditional \"am__fastdepCC\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ATPS_TRUE}" && test -z "${ATPS_FALSE}"; then as_fn_error $? "conditional \"ATPS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${CONDITIONAL_TRUE}" && test -z "${CONDITIONAL_FALSE}"; then as_fn_error $? "conditional \"CONDITIONAL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${REPLACE_RULES_TRUE}" && test -z "${REPLACE_RULES_FALSE}"; then as_fn_error $? "conditional \"REPLACE_RULES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${REPRRD_TRUE}" && test -z "${REPRRD_FALSE}"; then as_fn_error $? "conditional \"REPRRD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${REPUTE_TRUE}" && test -z "${REPUTE_FALSE}"; then as_fn_error $? "conditional \"REPUTE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${STATS_TRUE}" && test -z "${STATS_FALSE}"; then as_fn_error $? "conditional \"STATS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${RBL_TRUE}" && test -z "${RBL_FALSE}"; then as_fn_error $? "conditional \"RBL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${VBR_TRUE}" && test -z "${VBR_FALSE}"; then as_fn_error $? "conditional \"VBR\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${RPATH_TRUE}" && test -z "${RPATH_FALSE}"; then as_fn_error $? "conditional \"RPATH\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LCOV_TRUE}" && test -z "${LCOV_FALSE}"; then as_fn_error $? "conditional \"LCOV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GCOV_TRUE}" && test -z "${GCOV_FALSE}"; then as_fn_error $? "conditional \"GCOV\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GCOV_ONLY_TRUE}" && test -z "${GCOV_ONLY_FALSE}"; then as_fn_error $? "conditional \"GCOV_ONLY\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GPROF_TRUE}" && test -z "${GPROF_FALSE}"; then as_fn_error $? "conditional \"GPROF\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${GPROF_FILENAMES_TRUE}" && test -z "${GPROF_FILENAMES_FALSE}"; then as_fn_error $? "conditional \"GPROF_FILENAMES\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${BUILD_FILTER_TRUE}" && test -z "${BUILD_FILTER_FALSE}"; then as_fn_error $? "conditional \"BUILD_FILTER\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ALL_SYMBOLS_TRUE}" && test -z "${ALL_SYMBOLS_FALSE}"; then as_fn_error $? "conditional \"ALL_SYMBOLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${DEBUG_TRUE}" && test -z "${DEBUG_FALSE}"; then as_fn_error $? "conditional \"DEBUG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_GNUTLS_TRUE}" && test -z "${USE_GNUTLS_FALSE}"; then as_fn_error $? "conditional \"USE_GNUTLS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_RRD_TRUE}" && test -z "${USE_RRD_FALSE}"; then as_fn_error $? "conditional \"USE_RRD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_LIBMEMCACHED_TRUE}" && test -z "${USE_LIBMEMCACHED_FALSE}"; then as_fn_error $? "conditional \"USE_LIBMEMCACHED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_UNBOUND_TRUE}" && test -z "${USE_UNBOUND_FALSE}"; then as_fn_error $? "conditional \"USE_UNBOUND\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_TRE_TRUE}" && test -z "${USE_TRE_FALSE}"; then as_fn_error $? "conditional \"USE_TRE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LUA_TRUE}" && test -z "${LUA_FALSE}"; then as_fn_error $? "conditional \"LUA\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_ODBX_TRUE}" && test -z "${USE_ODBX_FALSE}"; then as_fn_error $? "conditional \"USE_ODBX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_LDAP_TRUE}" && test -z "${USE_LDAP_FALSE}"; then as_fn_error $? "conditional \"USE_LDAP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_SASL_TRUE}" && test -z "${USE_SASL_FALSE}"; then as_fn_error $? "conditional \"USE_SASL\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_MDB_TRUE}" && test -z "${USE_MDB_FALSE}"; then as_fn_error $? "conditional \"USE_MDB\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${JANSSON_TRUE}" && test -z "${JANSSON_FALSE}"; then as_fn_error $? "conditional \"JANSSON\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_DB_OPENDKIM_TRUE}" && test -z "${USE_DB_OPENDKIM_FALSE}"; then as_fn_error $? "conditional \"USE_DB_OPENDKIM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${USE_DB_LIBOPENDKIM_TRUE}" && test -z "${USE_DB_LIBOPENDKIM_FALSE}"; then as_fn_error $? "conditional \"USE_DB_LIBOPENDKIM\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${LIVE_TESTS_TRUE}" && test -z "${LIVE_TESTS_FALSE}"; then as_fn_error $? "conditional \"LIVE_TESTS\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${TEST_SOCKET_TRUE}" && test -z "${TEST_SOCKET_FALSE}"; then as_fn_error $? "conditional \"TEST_SOCKET\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${ERLANG_TRUE}" && test -z "${ERLANG_FALSE}"; then as_fn_error $? "conditional \"ERLANG\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi : "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 $as_echo "$as_me: creating $CONFIG_STATUS" >&6;} as_write_fail=0 cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 #! $SHELL # Generated by $as_me. # Run this file to recreate the current configuration. # Compiler output produced by configure, useful for debugging # configure, is in config.log if it exists. debug=false ac_cs_recheck=false ac_cs_silent=false SHELL=\${CONFIG_SHELL-$SHELL} export SHELL _ASEOF cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 ## -------------------- ## ## M4sh Initialization. ## ## -------------------- ## # Be more Bourne compatible DUALCASE=1; export DUALCASE # for MKS sh if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : emulate sh NULLCMD=: # Pre-4.2 versions of Zsh do 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 as_nl=' ' export as_nl # Printing a long string crashes Solaris 7 /usr/bin/printf. as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo # Prefer a ksh shell builtin over an external printf program on Solaris, # but without wasting forks for bash or zsh. if test -z "$BASH_VERSION$ZSH_VERSION" \ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='print -r --' as_echo_n='print -rn --' elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then as_echo='printf %s\n' as_echo_n='printf %s' else if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' as_echo_n='/usr/ucb/echo -n' else as_echo_body='eval expr "X$1" : "X\\(.*\\)"' as_echo_n_body='eval arg=$1; case $arg in #( *"$as_nl"*) expr "X$arg" : "X\\(.*\\)$as_nl"; arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; esac; expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" ' export as_echo_n_body as_echo_n='sh -c $as_echo_n_body as_echo' fi export as_echo_body as_echo='sh -c $as_echo_body as_echo' fi # The user is always right. if test "${PATH_SEPARATOR+set}" != set; then PATH_SEPARATOR=: (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || PATH_SEPARATOR=';' } fi # IFS # We need space, tab and new line, in precisely that order. Quoting is # there to prevent editors from complaining about space-tab. # (If _AS_PATH_WALK were called with IFS unset, it would disable word # splitting by setting IFS to empty value.) IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break done IFS=$as_save_IFS ;; esac # We did not find ourselves, most probably we were run as `sh COMMAND' # in which case we are not to be found in the path. if test "x$as_myself" = x; then as_myself=$0 fi if test ! -f "$as_myself"; then $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 exit 1 fi # Unset variables that we do not need and which cause bugs (e.g. in # pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" # suppresses any "Segmentation fault" message there. '((' could # trigger a bug in pdksh 5.2.14. for as_var in BASH_ENV ENV MAIL MAILPATH do eval test x\${$as_var+set} = xset \ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : done PS1='$ ' PS2='> ' PS4='+ ' # NLS nuisances. LC_ALL=C export LC_ALL LANGUAGE=C export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH # as_fn_error STATUS ERROR [LINENO LOG_FD] # ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the # script with STATUS, using 1 if that was 0. as_fn_error () { as_status=$1; test $as_status -eq 0 && as_status=1 if test "$4"; then as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error # as_fn_set_status STATUS # ----------------------- # Set $? to STATUS, without forking. as_fn_set_status () { return $1 } # as_fn_set_status # as_fn_exit STATUS # ----------------- # Exit the shell with STATUS, even in a "trap 0" or "set -e" context. as_fn_exit () { set +e as_fn_set_status $1 exit $1 } # as_fn_exit # as_fn_unset VAR # --------------- # Portably unset VAR. as_fn_unset () { { eval $1=; unset $1;} } as_unset=as_fn_unset # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take # advantage of any shell optimizations that allow amortized linear growth over # repeated appends, instead of the typical quadratic growth present in naive # implementations. if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : eval 'as_fn_append () { eval $1+=\$2 }' else as_fn_append () { eval $1=\$$1\$2 } fi # as_fn_append # as_fn_arith ARG... # ------------------ # Perform arithmetic evaluation on the ARGs, and store the result in the # global $as_val. Take advantage of shells that can avoid forks. The arguments # must be portable across $(()) and expr. if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : eval 'as_fn_arith () { as_val=$(( $* )) }' else as_fn_arith () { as_val=`expr "$@" || test $? -eq 1` } fi # as_fn_arith if expr a : '\(a\)' >/dev/null 2>&1 && test "X`expr 00001 : '.*\(...\)'`" = X001; then as_expr=expr else as_expr=false fi if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then as_basename=basename else as_basename=false fi if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then as_dirname=dirname else as_dirname=false fi as_me=`$as_basename -- "$0" || $as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ X"$0" : 'X\(//\)$' \| \ X"$0" : 'X\(/\)' \| . 2>/dev/null || $as_echo X/"$0" | sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } /^X\/\(\/\/\)$/{ s//\1/ q } /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` # Avoid depending upon Character Ranges. as_cr_letters='abcdefghijklmnopqrstuvwxyz' as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' as_cr_Letters=$as_cr_letters$as_cr_LETTERS as_cr_digits='0123456789' as_cr_alnum=$as_cr_Letters$as_cr_digits ECHO_C= ECHO_N= ECHO_T= case `echo -n x` in #((((( -n*) case `echo 'xy\c'` in *c*) ECHO_T=' ';; # ECHO_T is single tab character. xy) ECHO_C='\c';; *) echo `echo ksh88 bug on AIX 6.1` > /dev/null ECHO_T=' ';; esac;; *) ECHO_N='-n';; esac rm -f conf$$ conf$$.exe conf$$.file if test -d conf$$.dir; then rm -f conf$$.dir/conf$$.file else rm -f conf$$.dir mkdir conf$$.dir 2>/dev/null fi if (echo >conf$$.file) 2>/dev/null; then if ln -s conf$$.file conf$$ 2>/dev/null; then as_ln_s='ln -s' # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else as_ln_s='cp -pR' fi else as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null # as_fn_mkdir_p # ------------- # Create "$as_dir" as a directory, including parents if necessary. as_fn_mkdir_p () { case $as_dir in #( -*) as_dir=./$as_dir;; esac test -d "$as_dir" || eval $as_mkdir_p || { as_dirs= while :; do case $as_dir in #( *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( *) as_qdir=$as_dir;; esac as_dirs="'$as_qdir' $as_dirs" as_dir=`$as_dirname -- "$as_dir" || $as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$as_dir" : 'X\(//\)[^/]' \| \ X"$as_dir" : 'X\(//\)$' \| \ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$as_dir" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p if mkdir -p . 2>/dev/null; then as_mkdir_p='mkdir -p "$as_dir"' else test -d ./-p && rmdir ./-p as_mkdir_p=false fi # as_fn_executable_p FILE # ----------------------- # Test if FILE is an executable regular file. as_fn_executable_p () { test -f "$1" && test -x "$1" } # as_fn_executable_p as_test_x='test -x' as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" exec 6>&1 ## ----------------------------------- ## ## Main body of $CONFIG_STATUS script. ## ## ----------------------------------- ## _ASEOF test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by OpenDKIM $as_me 2.11.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ on `(hostname || uname -n) 2>/dev/null | sed 1q` " _ACEOF case $ac_config_files in *" "*) set x $ac_config_files; shift; ac_config_files=$*;; esac case $ac_config_headers in *" "*) set x $ac_config_headers; shift; ac_config_headers=$*;; esac cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # Files that config.status was made for. config_files="$ac_config_files" config_headers="$ac_config_headers" config_commands="$ac_config_commands" _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 ac_cs_usage="\ \`$as_me' instantiates files and other configuration actions from templates according to the current configuration. Unless the files and actions are specified as TAGs, all are instantiated by default. Usage: $0 [OPTION]... [TAG]... -h, --help print this help, then exit -V, --version print version number and configuration settings, then exit --config print configuration, then exit -q, --quiet, --silent do not print progress messages -d, --debug don't remove temporary files --recheck update $as_me by reconfiguring in the same conditions --file=FILE[:TEMPLATE] instantiate the configuration file FILE --header=FILE[:TEMPLATE] instantiate the configuration header FILE Configuration files: $config_files Configuration headers: $config_headers Configuration commands: $config_commands Report bugs to ." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ OpenDKIM config.status 2.11.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' INSTALL='$INSTALL' MKDIR_P='$MKDIR_P' AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # The default lists apply if the user does not specify any file. ac_need_defaults=: while test $# != 0 do case $1 in --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; --*=) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg= ac_shift=: ;; *) ac_option=$1 ac_optarg=$2 ac_shift=shift ;; esac case $ac_option in # Handling of the options. -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) ac_cs_recheck=: ;; --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) $as_echo "$ac_cs_version"; exit ;; --config | --confi | --conf | --con | --co | --c ) $as_echo "$ac_cs_config"; exit ;; --debug | --debu | --deb | --de | --d | -d ) debug=: ;; --file | --fil | --fi | --f ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; --header | --heade | --head | --hea ) $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; esac as_fn_append CONFIG_HEADERS " '$ac_optarg'" ac_need_defaults=false;; --he | --h) # Conflict between --help and --header as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; -q | -quiet | --quiet | --quie | --qui | --qu | --q \ | -silent | --silent | --silen | --sile | --sil | --si | --s) ac_cs_silent=: ;; # This is an error. -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" ac_need_defaults=false ;; esac shift done ac_configure_extra_args= if $ac_cs_silent; then exec 6>/dev/null ac_configure_extra_args="$ac_configure_extra_args --silent" fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' export CONFIG_SHELL exec "\$@" fi _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 exec 5>>config.log { echo sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX ## Running $as_me. ## _ASBOX $as_echo "$ac_log" } >&5 _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" # 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 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' # A function that is used when there is no print builtin or printf. func_fallback_echo () { eval 'cat <<_LTECHO_EOF \$1 _LTECHO_EOF' } # Quote evaled strings. for var in SHELL \ ECHO \ SED \ GREP \ EGREP \ FGREP \ LD \ NM \ LN_S \ lt_SP2NL \ lt_NL2SP \ reload_flag \ OBJDUMP \ deplibs_check_method \ file_magic_cmd \ file_magic_glob \ want_nocaseglob \ DLLTOOL \ sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ archiver_list_spec \ STRIP \ RANLIB \ CC \ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ nm_file_list_spec \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_pic \ lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ OTOOL \ OTOOL64 \ shrext_cmds \ export_dynamic_flag_spec \ whole_archive_flag_spec \ compiler_needs_object \ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ exclude_expsyms \ include_expsyms \ file_list_spec \ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ install_override_mode \ finish_eval \ old_striplib \ striplib; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done # Double-quote double-evaled strings. for var in reload_cmds \ old_postinstall_cmds \ old_postuninstall_cmds \ old_archive_cmds \ extract_expsyms_cmds \ old_archive_from_new_cmds \ old_archive_from_expsyms_cmds \ archive_cmds \ archive_expsym_cmds \ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" ;; esac done ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes INIT. if test -n "\${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Handling of arguments. for ac_config_target in $ac_config_targets do case $ac_config_target in "build-config.h") CONFIG_HEADERS="$CONFIG_HEADERS build-config.h" ;; "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;; "autobuild/Makefile") CONFIG_FILES="$CONFIG_FILES autobuild/Makefile" ;; "contrib/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/Makefile" ;; "contrib/convert/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/convert/Makefile" ;; "contrib/docs/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/docs/Makefile" ;; "contrib/init/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/init/Makefile" ;; "contrib/init/generic/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/init/generic/Makefile" ;; "contrib/init/redhat/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/init/redhat/Makefile" ;; "contrib/init/redhat/opendkim") CONFIG_FILES="$CONFIG_FILES contrib/init/redhat/opendkim" ;; "contrib/init/redhat/opendkim-default-keygen") CONFIG_FILES="$CONFIG_FILES contrib/init/redhat/opendkim-default-keygen" ;; "contrib/init/solaris/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/init/solaris/Makefile" ;; "contrib/ldap/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/ldap/Makefile" ;; "contrib/lua/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/lua/Makefile" ;; "contrib/patches/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/patches/Makefile" ;; "contrib/repute/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/repute/Makefile" ;; "contrib/spec/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/spec/Makefile" ;; "contrib/spec/opendkim.spec") CONFIG_FILES="$CONFIG_FILES contrib/spec/opendkim.spec" ;; "contrib/stats/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/stats/Makefile" ;; "contrib/systemd/Makefile") CONFIG_FILES="$CONFIG_FILES contrib/systemd/Makefile" ;; "contrib/systemd/opendkim.service") CONFIG_FILES="$CONFIG_FILES contrib/systemd/opendkim.service" ;; "libopendkim/opendkim.pc") CONFIG_FILES="$CONFIG_FILES libopendkim/opendkim.pc" ;; "libopendkim/Makefile") CONFIG_FILES="$CONFIG_FILES libopendkim/Makefile" ;; "libopendkim/docs/Makefile") CONFIG_FILES="$CONFIG_FILES libopendkim/docs/Makefile" ;; "libopendkim/tests/Makefile") CONFIG_FILES="$CONFIG_FILES libopendkim/tests/Makefile" ;; "librbl/rbl.pc") CONFIG_FILES="$CONFIG_FILES librbl/rbl.pc" ;; "librbl/Makefile") CONFIG_FILES="$CONFIG_FILES librbl/Makefile" ;; "libut/ut.pc") CONFIG_FILES="$CONFIG_FILES libut/ut.pc" ;; "libut/Makefile") CONFIG_FILES="$CONFIG_FILES libut/Makefile" ;; "libvbr/vbr.pc") CONFIG_FILES="$CONFIG_FILES libvbr/vbr.pc" ;; "libvbr/Makefile") CONFIG_FILES="$CONFIG_FILES libvbr/Makefile" ;; "miltertest/Makefile") CONFIG_FILES="$CONFIG_FILES miltertest/Makefile" ;; "opendkim/Makefile") CONFIG_FILES="$CONFIG_FILES opendkim/Makefile" ;; "opendkim/opendkim.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim.8" ;; "opendkim/opendkim-genkey") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-genkey" ;; "opendkim/opendkim-genkey.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-genkey.8" ;; "opendkim/opendkim-genzone.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-genzone.8" ;; "opendkim/opendkim-lua.3") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-lua.3" ;; "opendkim/opendkim-testkey.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-testkey.8" ;; "opendkim/opendkim-stats.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-stats.8" ;; "opendkim/opendkim-testmsg.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-testmsg.8" ;; "opendkim/opendkim.conf.5") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim.conf.5" ;; "opendkim/opendkim.conf.simple") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim.conf.simple" ;; "opendkim/opendkim.conf.simple-verify") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim.conf.simple-verify" ;; "opendkim/opendkim-atpszone.8") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-atpszone.8" ;; "opendkim/opendkim-spam.1") CONFIG_FILES="$CONFIG_FILES opendkim/opendkim-spam.1" ;; "opendkim/tests/Makefile") CONFIG_FILES="$CONFIG_FILES opendkim/tests/Makefile" ;; "stats/Makefile") CONFIG_FILES="$CONFIG_FILES stats/Makefile" ;; "stats/opendkim-importstats.8") CONFIG_FILES="$CONFIG_FILES stats/opendkim-importstats.8" ;; "stats/opendkim-expire") CONFIG_FILES="$CONFIG_FILES stats/opendkim-expire" ;; "stats/opendkim-expire.8") CONFIG_FILES="$CONFIG_FILES stats/opendkim-expire.8" ;; "stats/opendkim-gengraphs") CONFIG_FILES="$CONFIG_FILES stats/opendkim-gengraphs" ;; "stats/opendkim-gengraphs.8") CONFIG_FILES="$CONFIG_FILES stats/opendkim-gengraphs.8" ;; "stats/opendkim-genstats") CONFIG_FILES="$CONFIG_FILES stats/opendkim-genstats" ;; "stats/opendkim-genstats.8") CONFIG_FILES="$CONFIG_FILES stats/opendkim-genstats.8" ;; "stats/opendkim-reportstats") CONFIG_FILES="$CONFIG_FILES stats/opendkim-reportstats" ;; "reprrd/Makefile") CONFIG_FILES="$CONFIG_FILES reprrd/Makefile" ;; "reprrd/opendkim-reprrdimport") CONFIG_FILES="$CONFIG_FILES reprrd/opendkim-reprrdimport" ;; "reprrd/opendkim-reprrdimport.8") CONFIG_FILES="$CONFIG_FILES reprrd/opendkim-reprrdimport.8" ;; "reprrd/reprrd.pc") CONFIG_FILES="$CONFIG_FILES reprrd/reprrd.pc" ;; "reputation/Makefile") CONFIG_FILES="$CONFIG_FILES reputation/Makefile" ;; "reputation/opendkim-genrates") CONFIG_FILES="$CONFIG_FILES reputation/opendkim-genrates" ;; "reputation/opendkim-genrates.8") CONFIG_FILES="$CONFIG_FILES reputation/opendkim-genrates.8" ;; "reputation/opendkim-modtotals") CONFIG_FILES="$CONFIG_FILES reputation/opendkim-modtotals" ;; "reputation/opendkim-modtotals.8") CONFIG_FILES="$CONFIG_FILES reputation/opendkim-modtotals.8" ;; "reputation/opendkim-rephistory") CONFIG_FILES="$CONFIG_FILES reputation/opendkim-rephistory" ;; "reputation/opendkim-rephistory.8") CONFIG_FILES="$CONFIG_FILES reputation/opendkim-rephistory.8" ;; "reputation/repute.pc") CONFIG_FILES="$CONFIG_FILES reputation/repute.pc" ;; *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done # If the user did not use the arguments to specify the items to instantiate, # then the envvar interface is used. Set only those that are not. # We use the long form for the default assignment because of an extremely # bizarre bug on SunOS 4.1.3. if $ac_need_defaults; then test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands fi # Have a temporary directory for convenience. Make it in the build tree # simply because there is no reason against having it here, and in addition, # creating and moving files from /tmp can sometimes cause problems. # Hook for its removal unless debugging. # Note that there is a small window in which the directory will not be cleaned: # after its creation but before its name has been assigned to `$tmp'. $debug || { tmp= ac_tmp= trap 'exit_status=$? : "${ac_tmp:=$tmp}" { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } # Create a (secure) tmp directory for tmp files. { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") } || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. # This happens for instance with `./config.status config.h'. if test -n "$CONFIG_FILES"; then ac_cr=`echo X | tr X '\015'` # On cygwin, bash can eat \r inside `` if the user requested igncr. # But we know of no other shell where ac_cr would be empty at this # point, so we can use a bashism as a fallback. if test "x$ac_cr" = x; then eval ac_cr=\$\'\\r\' fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF { echo "cat >conf$$subs.awk <<_ACEOF" && echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h s/^/S["/; s/!.*/"]=/ p g s/^[^!]*!// :repl t repl s/'"$ac_delim"'$// t delim :nl h s/\(.\{148\}\)..*/\1/ t more1 s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ p n b repl :more1 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t nl :delim h s/\(.\{148\}\)..*/\1/ t more2 s/["\\]/\\&/g; s/^/"/; s/$/"/ p b :more2 s/["\\]/\\&/g; s/^/"/; s/$/"\\/ p g s/.\{148\}// t delim ' >$CONFIG_STATUS || ac_write_fail=1 rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" } { line = $ 0 nfields = split(line, field, "@") substed = 0 len = length(field[1]) for (i = 2; i < nfields; i++) { key = field[i] keylen = length(key) if (S_is_set[key]) { value = S[key] line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) len += length(value) + length(field[++i]) substed = 1 } else len += 1 + keylen } print line } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF # VPATH may cause trouble with some makes, so we remove sole $(srcdir), # ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ h s/// s/^/:/ s/[ ]*$/:/ s/:\$(srcdir):/:/g s/:\${srcdir}:/:/g s/:@srcdir@:/:/g s/^:*// s/:*$// x s/\(=[ ]*\).*/\1/ G s/\n// s/^[^=]*=[ ]*$// }' fi cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 fi # test -n "$CONFIG_FILES" # Set up the scripts for CONFIG_HEADERS section. # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF # Transform confdefs.h into an awk script `defines.awk', embedded as # here-document in config.status, that substitutes the proper values into # config.h.in to produce config.h. # Create a delimiter string that does not exist in confdefs.h, to ease # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do ac_tt=`sed -n "/$ac_delim/p" confdefs.h` if test -z "$ac_tt"; then break elif $ac_last_try; then as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi done # For the awk script, D is an array of macro values keyed by name, # likewise P contains macro parameters if any. Preserve backslash # newline sequences. ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* sed -n ' s/.\{148\}/&'"$ac_delim"'/g t rset :rset s/^[ ]*#[ ]*define[ ][ ]*/ / t def d :def s/\\$// t bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3"/p s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p d :bsnl s/["\\]/\\&/g s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ D["\1"]=" \3\\\\\\n"\\/p t cont s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p t cont d :cont n s/.\{148\}/&'"$ac_delim"'/g t clear :clear s/\\$// t bsnlc s/["\\]/\\&/g; s/^/"/; s/$/"/p d :bsnlc s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p b cont ' >$CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 for (key in D) D_is_set[key] = 1 FS = "" } /^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { line = \$ 0 split(line, arg, " ") if (arg[1] == "#") { defundef = arg[2] mac1 = arg[3] } else { defundef = substr(arg[1], 2) mac1 = arg[2] } split(mac1, mac2, "(") #) macro = mac2[1] prefix = substr(line, 1, index(line, defundef) - 1) if (D_is_set[macro]) { # Preserve the white space surrounding the "#". print prefix "define", macro P[macro] D[macro] next } else { # Replace #undef with comments. This is necessary, for example, # in the case of _POSIX_SOURCE, which is predefined and required # on some systems where configure will not decide to define it. if (defundef == "undef") { print "/*", prefix defundef, macro, "*/" next } } } { print } _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" shift for ac_tag do case $ac_tag in :[FHLC]) ac_mode=$ac_tag; continue;; esac case $ac_mode$ac_tag in :[FHL]*:*);; :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac ac_save_IFS=$IFS IFS=: set x $ac_tag IFS=$ac_save_IFS shift ac_file=$1 shift case $ac_mode in :L) ac_source=$1;; :[FH]) ac_file_inputs= for ac_f do case $ac_f in -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. test -f "$ac_f" || case $ac_f in [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" done # Let's still pretend it is `configure' which instantiates (i.e., don't # use $as_me), people would be surprised to read: # /* config.h. Generated by config.status. */ configure_input='Generated from '` $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' `' by configure.' if test x"$ac_file" != x-; then configure_input="$ac_file. $configure_input" { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 $as_echo "$as_me: creating $ac_file" >&6;} fi # Neutralize special characters interpreted by sed in replacement strings. case $configure_input in #( *\&* | *\|* | *\\* ) ac_sed_conf_input=`$as_echo "$configure_input" | sed 's/[\\\\&|]/\\\\&/g'`;; #( *) ac_sed_conf_input=$configure_input;; esac case $ac_tag in *:-:* | *:-) cat >"$ac_tmp/stdin" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac ac_dir=`$as_dirname -- "$ac_file" || $as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$ac_file" : 'X\(//\)[^/]' \| \ X"$ac_file" : 'X\(//\)$' \| \ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$ac_file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir="$ac_dir"; as_fn_mkdir_p ac_builddir=. case "$ac_dir" in .) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` # A ".." for each directory in $ac_dir_suffix. ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` case $ac_top_builddir_sub in "") ac_top_builddir_sub=. ac_top_build_prefix= ;; *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; esac ;; esac ac_abs_top_builddir=$ac_pwd ac_abs_builddir=$ac_pwd$ac_dir_suffix # for backward compatibility: ac_top_builddir=$ac_top_build_prefix case $srcdir in .) # We are building in place. ac_srcdir=. ac_top_srcdir=$ac_top_builddir_sub ac_abs_top_srcdir=$ac_pwd ;; [\\/]* | ?:[\\/]* ) # Absolute name. ac_srcdir=$srcdir$ac_dir_suffix; ac_top_srcdir=$srcdir ac_abs_top_srcdir=$srcdir ;; *) # Relative name. ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix ac_top_srcdir=$ac_top_build_prefix$srcdir ac_abs_top_srcdir=$ac_pwd/$srcdir ;; esac ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix case $ac_mode in :F) # # CONFIG_FILE # case $INSTALL in [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; esac ac_MKDIR_P=$MKDIR_P case $MKDIR_P in [\\/$]* | ?:[\\/]* ) ;; */*) ac_MKDIR_P=$ac_top_build_prefix$MKDIR_P ;; esac _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # If the template does not know about datarootdir, expand it. # FIXME: This hack should be removed a few years after 2.60. ac_datarootdir_hack=; ac_datarootdir_seen= ac_sed_dataroot=' /datarootdir/ { p q } /@datadir@/p /@docdir@/p /@infodir@/p /@localedir@/p /@mandir@/p' case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in *datarootdir*) ac_datarootdir_seen=yes;; *@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 $as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_datarootdir_hack=' s&@datadir@&$datadir&g s&@docdir@&$docdir&g s&@infodir@&$infodir&g s&@localedir@&$localedir&g s&@mandir@&$mandir&g s&\\\${datarootdir}&$datarootdir&g' ;; esac _ACEOF # Neutralize VPATH when `$srcdir' = `.'. # Shell code in configure.ac might set extrasub. # FIXME: do we really want to maintain this feature? cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_sed_extra="$ac_vpsub $extrasub _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 :t /@[a-zA-Z_][a-zA-Z_0-9]*@/!b s|@configure_input@|$ac_sed_conf_input|;t t s&@top_builddir@&$ac_top_builddir_sub&;t t s&@top_build_prefix@&$ac_top_build_prefix&;t t s&@srcdir@&$ac_srcdir&;t t s&@abs_srcdir@&$ac_abs_srcdir&;t t s&@top_srcdir@&$ac_top_srcdir&;t t s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t s&@builddir@&$ac_builddir&;t t s&@abs_builddir@&$ac_abs_builddir&;t t s&@abs_top_builddir@&$ac_abs_top_builddir&;t t s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' which seems to be undefined. Please make sure it is defined" >&2;} rm -f "$ac_tmp/stdin" case $ac_file in -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # # CONFIG_HEADER # if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" } >"$ac_tmp/config.h" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" mv "$ac_tmp/config.h" "$ac_file" \ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" _am_stamp_count=1 for _am_header in $config_headers :; do case $_am_header in $_am_arg | $_am_arg:* ) break ;; * ) _am_stamp_count=`expr $_am_stamp_count + 1` ;; esac done echo "timestamp for $_am_arg" >`$as_dirname -- "$_am_arg" || $as_expr X"$_am_arg" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$_am_arg" : 'X\(//\)[^/]' \| \ X"$_am_arg" : 'X\(//\)$' \| \ X"$_am_arg" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$_am_arg" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'`/stamp-h$_am_stamp_count ;; :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 $as_echo "$as_me: executing $ac_file commands" >&6;} ;; esac case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. case $CONFIG_FILES in *\'*) eval set x "$CONFIG_FILES" ;; *) set x $CONFIG_FILES ;; esac shift for mf do # Strip MF so we end up with the name of the file. mf=`echo "$mf" | sed -e 's/:.*$//'` # Check whether this is an Automake generated Makefile or not. # We used to match only the files named 'Makefile.in', but # some people rename them; so instead we look at the file content. # Grep'ing the first line is not enough: some people post-process # each Makefile.in and add a new line on top of each file to say so. # Grep'ing the whole file is not good either: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then dirpart=`$as_dirname -- "$mf" || $as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$mf" : 'X\(//\)[^/]' \| \ X"$mf" : 'X\(//\)$' \| \ X"$mf" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` else continue fi # Extract the definition of DEPDIR, am__include, and am__quote # from the Makefile without running 'make'. DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` test -z "$DEPDIR" && continue am__include=`sed -n 's/^am__include = //p' < "$mf"` test -z "$am__include" && continue am__quote=`sed -n 's/^am__quote = //p' < "$mf"` # Find all dependency output files, they are included files with # $(DEPDIR) in their names. We invoke sed twice because it is the # simplest approach to changing $(DEPDIR) to its actual value in the # expansion. for file in `sed -n " s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g'`; do # Make sure the directory exists. test -f "$dirpart/$file" && continue fdir=`$as_dirname -- "$file" || $as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ X"$file" : 'X\(//\)[^/]' \| \ X"$file" : 'X\(//\)$' \| \ X"$file" : 'X\(/\)' \| . 2>/dev/null || $as_echo X"$file" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q } /^X\(\/\/\)[^/].*/{ s//\1/ q } /^X\(\/\/\)$/{ s//\1/ q } /^X\(\/\).*/{ s//\1/ q } s/.*/./; q'` as_dir=$dirpart/$fdir; as_fn_mkdir_p # echo "creating $dirpart/$file" echo '# dummy' > "$dirpart/$file" done done } ;; "libtool":C) # See if we are running on zsh, and set the options which allow our # commands through without removal of \ escapes. if test -n "${ZSH_VERSION+set}" ; then setopt NO_GLOB_SUBST fi cfgfile="${ofile}T" trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL # `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. # Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, # Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. # # GNU Libtool 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. # # As a special exception to the GNU General Public License, # if you distribute this file as part of a program or library that # is built using GNU Libtool, you may include this file under the # same distribution terms that you use for the rest of that program. # # GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy # can be downloaded from http://www.gnu.org/licenses/gpl.html, or # obtained by writing to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # The names of the tagged configurations supported by this script. available_tags="" # ### BEGIN LIBTOOL CONFIG # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision # Whether or not to build shared libraries. build_libtool_libs=$enable_shared # Whether or not to build static libraries. build_old_libs=$enable_static # What type of objects to build. pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install # Shell to use when invoking shell scripts. SHELL=$lt_SHELL # An echo program that protects backslashes. ECHO=$lt_ECHO # The host system. host_alias=$host_alias host=$host host_os=$host_os # The build system. build_alias=$build_alias build=$build build_os=$build_os # A sed program that does not truncate output. SED=$lt_SED # Sed that helps us avoid accidentally triggering echo(1) options like -n. Xsed="\$SED -e 1s/^X//" # A grep program that handles long lines. GREP=$lt_GREP # An ERE matcher. EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP # A BSD- or MS-compatible name lister. NM=$lt_NM # Whether we need soft or hard links. LN_S=$lt_LN_S # What is the maximum length of a command? max_cmd_len=$max_cmd_len # Object file suffix (normally "o"). objext=$ac_objext # Executable file suffix (normally ""). exeext=$exeext # whether the shell understands "unset". lt_unset=$lt_unset # turn spaces into newlines. SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP # convert \$build file names to \$host format. to_host_file_cmd=$lt_cv_to_host_file_cmd # convert \$build files to toolchain format. to_tool_file_cmd=$lt_cv_to_tool_file_cmd # An object symbol dumper. OBJDUMP=$lt_OBJDUMP # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method # Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd # How to find potential files when deplibs_check_method = "file_magic". file_magic_glob=$lt_file_magic_glob # Find potential files using nocaseglob when deplibs_check_method = "file_magic". want_nocaseglob=$lt_want_nocaseglob # DLL creation program. DLLTOOL=$lt_DLLTOOL # Command to associate shared and link libraries. sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd # The archiver. AR=$lt_AR # Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS # How to feed a file listing to the archiver. archiver_list_spec=$lt_archiver_list_spec # A symbol stripping program. STRIP=$lt_STRIP # Commands used to install an old-style archive. RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds # Whether to use a lock for old archive extraction. lock_old_archive_extraction=$lock_old_archive_extraction # A C compiler. LTCC=$lt_CC # LTCC compiler flags. LTCFLAGS=$lt_CFLAGS # Take the output of nm and produce a listing of raw symbols and C names. global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix # Specify filename containing input files for \$NM. nm_file_list_spec=$lt_nm_file_list_spec # The root where to search for dependent libraries,and in which our libraries should be installed. lt_sysroot=$lt_sysroot # The name of the directory that contains temporary libtool files. objdir=$objdir # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks # Manifest tool. MANIFEST_TOOL=$lt_MANIFEST_TOOL # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL # Tool to change global to local symbols on Mac OS X. NMEDIT=$lt_NMEDIT # Tool to manipulate fat objects and archives on Mac OS X. LIPO=$lt_LIPO # ldd/readelf like tool for Mach-O binaries on Mac OS X. OTOOL=$lt_OTOOL # ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. OTOOL64=$lt_OTOOL64 # Old archive suffix (normally "a"). libext=$libext # Shared library suffix (normally ".so"). shrext_cmds=$lt_shrext_cmds # The commands to extract the exported symbol list from a shared archive. extract_expsyms_cmds=$lt_extract_expsyms_cmds # Variables whose values should be saved in libtool wrapper scripts and # restored at link time. variables_saved_for_relink=$lt_variables_saved_for_relink # Do we need the "lib" prefix for modules? need_lib_prefix=$need_lib_prefix # Do we need a version for libraries? need_version=$need_version # Library versioning type. version_type=$version_type # Shared library runtime path variable. runpath_var=$runpath_var # Shared library path variable. shlibpath_var=$shlibpath_var # Is shlibpath searched before the hard-coded library search path? shlibpath_overrides_runpath=$shlibpath_overrides_runpath # Format of library name prefix. libname_spec=$lt_libname_spec # List of archive names. First name is the real one, the rest are links. # The last name is the one that the linker finds with -lNAME library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec # Permission mode override for installation of shared libraries. install_override_mode=$lt_install_override_mode # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds # Command to use after uninstallation of a shared archive. postuninstall_cmds=$lt_postuninstall_cmds # Commands used to finish a libtool library installation in a directory. finish_cmds=$lt_finish_cmds # As "finish_cmds", except a single script fragment to be evaled but # not shown. finish_eval=$lt_finish_eval # Whether we should hardcode library paths into libraries. hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec # Run-time system search path for libraries. sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec # Whether dlopen is supported. dlopen_support=$enable_dlopen # Whether dlopen of programs is supported. dlopen_self=$enable_dlopen_self # Whether dlopen of statically linked programs is supported. dlopen_self_static=$enable_dlopen_self_static # Commands to strip libraries. old_striplib=$lt_old_striplib striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD # How to create reloadable object files. reload_flag=$lt_reload_flag reload_cmds=$lt_reload_cmds # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds # A language specific compiler. CC=$lt_compiler # Is the compiler the GNU compiler? with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic # How to pass a linker flag through the compiler. wl=$lt_lt_prog_compiler_wl # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static # Does compiler simultaneously support -c and -o options? compiler_c_o=$lt_lt_cv_prog_compiler_c_o # Whether or not to add -lc for building shared libraries. build_libtool_need_lc=$archive_cmds_need_lc # Whether or not to disallow shared libs when runtime libs are static. allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes # Compiler flag to allow reflexive dlopens. export_dynamic_flag_spec=$lt_export_dynamic_flag_spec # Compiler flag to generate shared objects directly from archives. whole_archive_flag_spec=$lt_whole_archive_flag_spec # Whether the compiler copes with passing no objects directly. compiler_needs_object=$lt_compiler_needs_object # Create an old-style archive from a shared archive. old_archive_from_new_cmds=$lt_old_archive_from_new_cmds # Create a temporary old-style archive to link instead of a shared archive. old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds # Commands used to build a shared archive. archive_cmds=$lt_archive_cmds archive_expsym_cmds=$lt_archive_expsym_cmds # Commands used to build a loadable module if different from building # a shared archive. module_cmds=$lt_module_cmds module_expsym_cmds=$lt_module_expsym_cmds # Whether we are building with GNU ld or not. with_gnu_ld=$lt_with_gnu_ld # Flag that allows shared libraries with undefined symbols to be built. allow_undefined_flag=$lt_allow_undefined_flag # Flag that enforces no undefined symbols. no_undefined_flag=$lt_no_undefined_flag # Flag to hardcode \$libdir into a binary during linking. # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec # If ld is used when linking, flag to hardcode \$libdir into a binary # during linking. This must work even if \$libdir does not exist. hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct # Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes # DIR into the resulting binary and the resulting library dependency is # "absolute",i.e impossible to change by setting \${shlibpath_var} if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute # Set to "yes" if using the -LDIR flag during linking hardcodes DIR # into the resulting binary. hardcode_minus_L=$hardcode_minus_L # Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR # into the resulting binary. hardcode_shlibpath_var=$hardcode_shlibpath_var # Set to "yes" if building a shared library automatically hardcodes DIR # into the library and all subsequent libraries and executables linked # against it. hardcode_automatic=$hardcode_automatic # Set to yes if linker adds runtime paths of dependent libraries # to runtime path list. inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols # The commands to list exported symbols. export_symbols_cmds=$lt_export_symbols_cmds # Symbols that should not be listed in the preloaded symbols. exclude_expsyms=$lt_exclude_expsyms # Symbols that must always be exported. include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds # Commands necessary for finishing linking programs. postlink_cmds=$lt_postlink_cmds # Specify filename containing input files. file_list_spec=$lt_file_list_spec # How to hardcode a shared library path into an executable. hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG _LT_EOF case $host_os in aix3*) cat <<\_LT_EOF >> "$cfgfile" # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. if test "X${COLLECT_NAMES+set}" != Xset; then COLLECT_NAMES= export COLLECT_NAMES fi _LT_EOF ;; esac ltmain="$ac_aux_dir/ltmain.sh" # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? sed '$q' "$ltmain" >> "$cfgfile" \ || (rm -f "$cfgfile"; exit 1) if test x"$xsi_shell" = xyes; then sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ func_dirname ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ } # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_basename ()$/,/^} # func_basename /c\ func_basename ()\ {\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ func_dirname_and_basename ()\ {\ \ case ${1} in\ \ */*) func_dirname_result="${1%/*}${2}" ;;\ \ * ) func_dirname_result="${3}" ;;\ \ esac\ \ func_basename_result="${1##*/}"\ } # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ func_stripname ()\ {\ \ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ \ # positional parameters, so assign one to ordinary parameter first.\ \ func_stripname_result=${3}\ \ func_stripname_result=${func_stripname_result#"${1}"}\ \ func_stripname_result=${func_stripname_result%"${2}"}\ } # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ func_split_long_opt ()\ {\ \ func_split_long_opt_name=${1%%=*}\ \ func_split_long_opt_arg=${1#*=}\ } # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ func_split_short_opt ()\ {\ \ func_split_short_opt_arg=${1#??}\ \ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ } # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ func_lo2o ()\ {\ \ case ${1} in\ \ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ \ *) func_lo2o_result=${1} ;;\ \ esac\ } # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_xform ()$/,/^} # func_xform /c\ func_xform ()\ {\ func_xform_result=${1%.*}.lo\ } # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_arith ()$/,/^} # func_arith /c\ func_arith ()\ {\ func_arith_result=$(( $* ))\ } # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_len ()$/,/^} # func_len /c\ func_len ()\ {\ func_len_result=${#1}\ } # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$lt_shell_append" = xyes; then sed -e '/^func_append ()$/,/^} # func_append /c\ func_append ()\ {\ eval "${1}+=\\${2}"\ } # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ func_append_quoted ()\ {\ \ func_quote_for_eval "${2}"\ \ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ } # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: # Save a `func_append' function call where possible by direct use of '+=' sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: else # Save a `func_append' function call even when '+=' is not available sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ && mv -f "$cfgfile.tmp" "$cfgfile" \ || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") test 0 -eq $? || _lt_function_replace_fail=: fi if test x"$_lt_function_replace_fail" = x":"; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 $as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} fi mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" ;; esac done # for ac_tag as_fn_exit 0 _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. # config.status does its own redirection, appending to config.log. # Unfortunately, on DOS this fails, as config.log is still kept open # by configure, so config.status won't be able to write to it; its # output is simply discarded. So we exec the FD to /dev/null, # effectively closing config.log, so it can be properly (re)opened and # appended to by config.status. When coming back to configure, we # need to make the FD available again. if test "$no_create" != yes; then ac_cs_success=: ac_config_status_args= test "$silent" = yes && ac_config_status_args="$ac_config_status_args --quiet" exec 5>/dev/null $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi OpenDKIM-rel-opendkim-2-11-0-Beta2/configure.ac000066400000000000000000002064071337314105200207540ustar00rootroot00000000000000# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. # # Copyright (c) 2009-2015, 2018, The Trusted Domain Project. # All rights reserved. # # # Setup # AC_PREREQ(2.61) # # Package version # m4_define([VERSION_RELEASE], 2) m4_define([VERSION_MAJOR_REV], 11) m4_define([VERSION_MINOR_REV], 0) m4_define([VERSION_PATCH], 0) # # Library version # - bump "current" and reset "revision" with API changes # - bump "revision" with internal source code changes # m4_define([LIBVERSION_CURRENT], 11) m4_define([LIBVERSION_REVISION], 0) m4_define([LIBVERSION_AGE], 0) # # Autotools setup # AC_INIT([OpenDKIM], [VERSION_RELEASE.VERSION_MAJOR_REV.VERSION_MINOR_REV], [bugs@opendkim.org]) AC_CONFIG_AUX_DIR([build-aux]) AM_INIT_AUTOMAKE( 1.11.1 dnl Automake version before 1.13 (when the serial-tests option was dnl still the default) still defined the badly obsolete macro dnl 'AM_PROG_INSTALL'. m4_ifndef([AM_PROG_INSTALL], [serial-tests]) ) AC_CONFIG_HEADERS([build-config.h]) AC_CONFIG_MACRO_DIR([m4]) # # Hexadecimal version, for use in generating dkim.h # HEX_VERSION=$(printf %08x $(( ((VERSION_RELEASE << 8 | VERSION_MAJOR_REV) << 8 | VERSION_MINOR_REV) << 8| VERSION_PATCH ))) AC_SUBST([HEX_VERSION]) # # library version, passed to libtool # LIBOPENDKIM_VERSION_INFO=$(printf %d:%d:%d LIBVERSION_CURRENT LIBVERSION_REVISION LIBVERSION_AGE) AC_SUBST([LIBOPENDKIM_VERSION_INFO]) # # Checks for programs # AC_PROG_CC AC_PROG_CC_C99 AM_PROG_CC_C_O AC_PROG_LIBTOOL PKG_PROG_PKG_CONFIG # # Check for how to compile threaded stuff # AX_PTHREAD # # save outer values # outer_CFLAGS="$CFLAGS" outer_CPPFLAGS="$CPPFLAGS" outer_LDFLAGS="$LDFLAGS" outer_LIBS="$LIBS" # # Checks for libraries # saved_LIBS="$LIBS" LIBS="" AC_SEARCH_LIBS(inet_addr, nsl) LIBNSL_LIBS="$LIBS" LIBS="$saved_LIBS" AC_SUBST([LIBNSL_LIBS]) saved_LIBS="$LIBS" LIBS="" AC_SEARCH_LIBS(dlopen, dl) LIBDL_LIBS="$LIBS" LIBS="$saved_LIBS" AC_SUBST([LIBDL_LIBS]) AC_SEARCH_LIBS(socket, socket) AC_SEARCH_LIBS(inet_aton, resolv) AC_SEARCH_LIBS(inet_pton, resolv, AC_DEFINE(HAVE_INET_PTON, 1, [Define to 1 if you have the `inet_pton()' function.])) AC_SEARCH_LIBS(inet_ntop, resolv nsl, AC_DEFINE(HAVE_INET_NTOP, 1, [Define to 1 if you have the `inet_ntop()' function.])) AC_SEARCH_LIBS(getaddrinfo, resolv, AC_DEFINE(HAVE_GETADDRINFO, 1, [Define to 1 if you have the `getaddrinfo()' function.])) # You might find res_ninit() in system libraries or in libresolv or not # at all. The way AC_LANG_CALL finds out is it declares res_ninit() so # it can call it, then it sees if linking fails because of unresolved # symbols. Great, except glibc doesn't export res_ninit() -- it exports # __res_ninit() -- res_ninit() is a macro in resolv.h. So unless we # include resolv.h, we won't find res_ninit(), but when we do include # it, it conflicts with AC_LANG_CALL's redeclaration. Hmm. I guess the # only thing for it is to include resolv.h, don't redeclare res_ninit(), # and use the proper type signature when calling it. m4_rename([AC_LANG_CALL], [saved_AC_LANG_CALL]) m4_define([AC_LANG_CALL], [AC_LANG_PROGRAM([#include ], [return res_ninit(NULL);])]) AC_SEARCH_LIBS(res_ninit, resolv, AC_DEFINE(HAVE_RES_NINIT, 1, [Define to 1 if you have the `res_ninit()' function.])) m4_rename_force([saved_AC_LANG_CALL], [AC_LANG_CALL]) AC_SEARCH_LIBS(res_setservers, resolv bind, AC_DEFINE(HAVE_RES_SETSERVERS, 1, [Define to 1 if you have the `res_setservers()' function.])) AC_SEARCH_LIBS(getopt_long, iberty, AC_DEFINE(HAVE_GETOPT_LONG, 1, [Define to 1 if you have the `getopt_long()' function.])) AC_HEADER_RESOLV # # Check for types # AC_CHECK_TYPES([useconds_t]) # # See if libopendkim will need -lresolv # dnscheck=' #include "confdefs.h" #include #include #include #include int main() { res_mkquery (0, 0, 0, 0, 0, 0, 0, 0, 0); dn_expand (0, 0, 0, 0, 0); dn_skipname (0, 0); dn_comp (0, 0, 0, 0, 0); return 0; }' AC_MSG_CHECKING([whether the resolver works without -lresolv]) LIBRESOLV= AC_LINK_IFELSE([AC_LANG_SOURCE([ $dnscheck ])] , [ AC_MSG_RESULT(yes) ] , [ AC_MSG_RESULT(no) AC_MSG_CHECKING([whether the resolver works with -lresolv]) saved_LIBS="$LIBS" LIBS="$outer_LIBS -lresolv" AC_LINK_IFELSE([AC_LANG_SOURCE([ $dnscheck ])] , [ AC_MSG_RESULT(yes) LIBRESOLV=-lresolv ] , [ AC_MSG_RESULT(no) AC_MSG_ERROR([need workable resolver library]) ]) LIBS="$saved_LIBS" ]) AC_SUBST([LIBRESOLV]) # # Checks for header files # AC_CHECK_HEADERS([arpa/inet.h fcntl.h limits.h iso/limits_iso.h netdb.h netinet/in.h paths.h stdlib.h string.h sys/file.h sys/param.h sys/socket.h sys/time.h syslog.h unistd.h stdint.h]) # # Checks for typedefs, structures, and compiler characteristics. # AC_HEADER_STDBOOL AC_TYPE_UID_T AC_TYPE_MODE_T AC_TYPE_OFF_T AC_TYPE_PID_T AC_TYPE_SIZE_T AC_TYPE_SSIZE_T AC_TYPE_UINT16_T AC_TYPE_UINT32_T AC_TYPE_UINT64_T # # Checks for library functions. # AC_FUNC_FORK AC_FUNC_GETGROUPS AC_FUNC_MALLOC AC_FUNC_MKTIME AC_FUNC_REALLOC AC_CHECK_FUNCS([dup2 endpwent getcwd gethostname gethostbyname getaddrinfo gethostbyname2 gettimeofday isascii memchr memmove memset regcomp select socket strcasecmp strchr strdup strerror strncasecmp strrchr strstr strtol strtoul strtoull realpath strsep]) bsdstrl_h_found="no" strl_found="no" libstrl_found="no" strl_h_found="no" AC_CHECK_HEADERS([bsd/string.h], [bsdstrl_h_found="yes"]) AC_CHECK_FUNCS([strlcat strlcpy], [strl_found="yes"], [ saved_LIBS="$LIBS" LIBS="$outer_LIBS" AC_SEARCH_LIBS([strlcat], [bsd strl], [libstrl_found="yes"], [strl_found="no"]) AC_SEARCH_LIBS([strlcpy], [bsd strl], [libstrl_found="yes"], [strl_found="no"]) STRL_LIBS="$LIBS" LIBS="$saved_LIBS" ]) if test x"$libstrl_found" = x"yes" then LIBS="$LIBS $STRL_LIBS" fi # we need something above to have worked if test x"$strl_found" != x"yes" -a x"$libstrl_found" != x"yes" then AC_MSG_ERROR(no strlcpy/strlcat found) fi AC_CHECK_HEADERS([strl.h], [strl_h_found="yes"]) if test x"$strl_h_found" != x"yes" then strldirs="/usr/local/include/strl /usr/local/include /usr/include/strl" for d in $strldirs do AC_MSG_CHECKING([for strl.h in $d]) if test -f $d/strl.h then unset ac_cv_header_strl_h saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS -I$d" AC_CHECK_HEADERS([strl.h], [strl_h_found="yes"]) CPPFLAGS="$saved_CPPFLAGS" fi if test x"$strl_h_found" = x"yes" then CPPFLAGS="$CPPFLAGS -I$d" break fi done fi # we need to include if an installed strl.h was found and no # bsd/string.h was found if test x"$strl_h_found" = x"yes" -a x"$bsdstrl_h_found" = x"no" then AC_DEFINE([USE_STRL_H], 1, [Define to 1 if you need to include to get the `strlcat()' and `strlcpy()' functions.]) fi if test x"$bsdstrl_h_found" = x"yes" then AC_DEFINE([USE_BSD_H], 1, [Define to 1 if you need to include to get the `strlcat()' and `strlcpy()' functions.]) fi # # Checks for structure members # AC_CHECK_MEMBER([struct sockaddr_un.sun_len], AC_DEFINE([HAVE_SUN_LEN], [1], [Define if sockaddr_un has a sun_len member]), [], [[#include ]]) AC_CHECK_MEMBER([struct sockaddr_in.sin_len], AC_DEFINE([HAVE_SIN_LEN], [1], [Define if sockaddr_in has a sin_len member]), [], [[#include ]]) AC_CHECK_MEMBER([struct sockaddr_in6.sin6_len], AC_DEFINE([HAVE_SIN6_LEN], [1], [Define if sockaddr_in6 has a sin6_len member]), [], [[#include ]]) # # Library feature string and macros # LIBOPENDKIM_FEATURE_STRING="libopendkim $PACKAGE_VERSION:" AC_DEFUN([TR_UP], [m4_translit([AS_TR_SH([$1])], [a-z], [A-Z])]) AC_DEFUN([FEATURE], [notincluded="(Not enabled for this installation.)" AC_ARG_ENABLE($1, AS_HELP_STRING(--enable-$1, $2), AS_IF([test "x$enable_]$1[" = "xyes"], [ AC_SUBST(TR_UP($1)[_MANNOTICE], "") AC_DEFINE(TR_UP($1), 1, [enable $1 feature]) ], [ AC_SUBST(TR_UP($1)[_MANNOTICE], $notincluded) ]), AC_SUBST(TR_UP($1)[_MANNOTICE], $notincluded)) ]) AC_DEFUN([LIB_FEATURE], [FEATURE($1, $2) AS_IF([test "x$enable_]$1[" = "xyes"], [ LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING $1" ]) ]) AC_DEFUN([FFR_FEATURE], [experimentalnotincluded="(Experimental feature not enabled for this installation.)" AC_ARG_ENABLE($1, AS_HELP_STRING(--enable-$1, $2), AS_IF([test "x$enable_]$1[" = "xyes"], [ AC_DEFINE([_FFR_]TR_UP($1), 1, [enable $1 feature]) AC_SUBST(TR_UP($1)[_MANNOTICE], "(Note: Feature is experimental.)") ], [ AC_SUBST(TR_UP($1)[_MANNOTICE], $experimentalnotincluded) ]), AC_SUBST(TR_UP($1)[_MANNOTICE], $experimentalnotincluded)) ]) AC_DEFUN([LIB_FFR_FEATURE], [FFR_FEATURE($1, $2) AS_IF([test "x$enable_]$1[" = "xyes"], [ LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING $1" ]) ]) # # opendkim # FEATURE([popauth], [enable POP-before-SMTP support]) FFR_FEATURE([atps], [experimental Authorized Third Party Signers checks]) LIB_FFR_FEATURE([atps], [experimental Authorized Third Party Signers checks]) AM_CONDITIONAL([ATPS], [test x"$enable_atps" = x"yes"]) FFR_FEATURE([conditional], [experimental conditional signatures]) LIB_FFR_FEATURE([conditional], [experimental conditional signatures]) AM_CONDITIONAL([CONDITIONAL], [test x"$enable_conditional" = x"yes"]) FFR_FEATURE([db_handle_pools], [experimental database handle pools]) FFR_FEATURE([diffheaders], [compare signed and verified headers when possible]) LIB_FFR_FEATURE([diffheaders], [compare signed and verified headers when possible]) FFR_FEATURE([identity_header], [special header to set identity]) FFR_FEATURE([ldap_caching], [LDAP query piggybacking and caching]) FFR_FEATURE([postgresql_reconnect_hack], [hack to overcome PostgreSQL connection error detection bug]) FFR_FEATURE([rate_limit], [support for DKIM-based rate limiting]) FFR_FEATURE([replace_rules], [support for string substitution when signing]) AM_CONDITIONAL([REPLACE_RULES], [test x"$enable_replace_rules" = x"yes"]) FFR_FEATURE([reprrd], [support for experimental reputation checks using RRD]) AM_CONDITIONAL([REPRRD], [test x"$enable_reprrd" = x"yes"]) AC_CHECK_PROG([hasrrdtool], [rrdtool], [yes]) if test x"$enable_reprrd" = x"yes" -a x"$hasrrdtool" != x"yes" then AC_MSG_ERROR([--enable-reprrd requires rrdtool binary, not found]) fi FFR_FEATURE([reputation], [support for experimental reputation checks]) if test x"$enable_reputation" = x"yes" then AC_SEARCH_LIBS([ceil], [m]) fi AM_CONDITIONAL([REPUTE], [test x"$enable_reputation" = x"yes"]) FFR_FEATURE([resign], [support for one-step re-signing]) FFR_FEATURE([sender_macro], [macro to determine sender]) FFR_FEATURE([socketdb], [arbitrary socket data sets]) FFR_FEATURE([stats], [stats recording and reporting]) AM_CONDITIONAL([STATS], [test x"$enable_stats" = x"yes"]) FFR_FEATURE([statsext], [extended stats recording and reporting]) FFR_FEATURE([rbl], [Realtime Blacklist query support]) AM_CONDITIONAL([RBL], [test x"$enable_rbl" = x"yes"]) FFR_FEATURE([vbr], [Vouch-By-Reference support]) AM_CONDITIONAL([VBR], [test x"$enable_vbr" = x"yes"]) if test x"$enable_statsext" = x"yes" -a x"$enable_stats" != x"yes" then AC_MSG_ERROR([--enable-statsext requires --enable-stats]) fi FFR_FEATURE([default_sender], [default sender address]) # sendmail command AC_PATH_PROG([SENDMAIL_PATH], [sendmail], [/usr/sbin/sendmail], [/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/usr/lib:$PATH]) AC_DEFINE_UNQUOTED([SENDMAIL_PATH], "$ac_cv_path_SENDMAIL_PATH", [The path the the sendmail executable for report sending]) AC_SUBST([SENDMAIL_PATH]) # # use rpath at load time? # AC_ARG_ENABLE( [rpath], AS_HELP_STRING([--enable-rpath], [include library load paths in binaries]), , enable_rpath="yes") AM_CONDITIONAL([RPATH], [test x"$enable_rpath" = x"yes"]) if test x"$enable_rpath" != x"yes" then AC_MSG_RESULT([Suppressing -rpath use by libtool]) hardcode_libdir_flag_spec=" -D__LIBTOOL_NO_RPATH__ " chmod 0755 libtool fi # # test coverage/profiling stuff # AC_ARG_ENABLE([codecoverage], AS_HELP_STRING([--enable-codecoverage], [include code coverage/profiling code])) if test x"$enable_codecoverage" = x"yes" then # gcc can do all of them; Solaris cc can only do gprof AC_CHECK_PROG([hasgcc], [gcc], [yes]) AC_CHECK_PROG([hascc], [cc], [yes]) if test x"$hasgcc" != x"yes" -a x"$hascc" = x"yes" then if test x`cc -V 2>&1 | grep -c "Sun C"` = x"1" then hassuncc="yes" fi fi # figure out which profiling system to use AC_CHECK_PROG([hasgprof], [gprof], [yes]) AC_ARG_WITH(gprof, AS_HELP_STRING(--with-gprof, profiling with gprof), hasgprof="$withval") if test x"$hasgcc" = x"yes" then AC_CHECK_PROG([hasgcov], [gcov], [yes]) AC_ARG_WITH(gcov, AS_HELP_STRING(--with-gcov, profiling with gcov), hasgcov="$withval") AC_CHECK_PROG([haslcov], [lcov], [yes]) AC_ARG_WITH(lcov, AS_HELP_STRING(--with-lcov, profiling with lcov), haslcov="$withval") fi # bail if none if test x"$hasgprof" != x"yes" -a \ x"$hasgcov" != x"yes" -a \ x"$haslcov" != x"yes" then AC_MSG_ERROR([no supported test coverage packages found]) fi # see if there's a libgcov (OpenBSD doesn't have one) if test x"$hasgcov" = x"yes" -a x"$haslcov" != x"yes" then saved_LIBS="$LIBS" LIBS="$outer_LIBS" AC_SEARCH_LIBS([__gcov_init], [gcov]) GCOV_LIBS="$LIBS" LIBS="$saved_LIBS" fi COV_CFLAGS="" COV_LDFLAGS="" COV_LIBADD="" # sun profiling if test x"$hasgprof" = x"yes" -a \ x"$hasgcov" != x"yes" -a \ x"$hassuncc" = x"yes" then COV_CFLAGS="-g -xpg" COV_LDFLAGS="-g -xpg" # non-sun profiling elif test x"$hasgprof" = x"yes" -a \ x"$hasgcov" != x"yes" -a \ x"$hassuncc" != x"yes" then COV_CFLAGS="-g -pg" COV_LDFLAGS="-g -pg" # gcov profiling elif test x"$hasgcov" = x"yes" then COV_CFLAGS="-g -fprofile-arcs -ftest-coverage" COV_LIBADD="$GCOV_LIBS" fi AC_SUBST(COV_CFLAGS) AC_SUBST(COV_LDFLAGS) AC_SUBST(COV_LIBADD) fi # see if profiling-enabled binaries generate profile output with the # standard name "gmon.out" or ".gmon" gprof_gmon_out="unknown" if test x"$hasgprof" = x"yes" then gprofcheck=' int main() { long x; x = random(); }' AC_MSG_CHECKING([names of profiling output files]) saved_CFLAGS="$CFLAGS" saved_LDFLAGS="$LDFLAGS" CFLAGS="$CFLAGS $COV_CFLAGS" LDFLAGS="$LDFLAGS $COV_LDFLAGS" AC_RUN_IFELSE([AC_LANG_SOURCE([$gprofcheck])], [ if test -f "gmon.out" then gprof_gmon_out="yes" rm -f gmon.out AC_MSG_RESULT(gmon.out) else gprof_gmon_out="no" rm -f *.gmon AC_MSG_RESULT([.gmon]) fi ], [AC_MSG_RESULT(unknown)]) CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" fi AM_CONDITIONAL(LCOV, test x"$haslcov" = x"yes" -a x"$hasgcov" = x"yes") AM_CONDITIONAL(GCOV, test x"$hasgcov" = x"yes") AM_CONDITIONAL(GCOV_ONLY, test x"$hasgcov" = x"yes" -a x"$haslcov" != x"yes") AM_CONDITIONAL(GPROF, test x"$hasgprof" = x"yes" -a x"$hasgcov" != x"yes") AM_CONDITIONAL(GPROF_FILENAMES, test x"$gprof_gmon_out" = x"no") # # opendkim # AC_ARG_ENABLE([filter], AS_HELP_STRING([--disable-filter], [do not compile the opendkim filter]), [enable_filter=$enableval], [enable_filter=yes]) AM_CONDITIONAL([BUILD_FILTER], [test x"$enable_filter" != x"no"]) # # libopendkim # LIB_FEATURE([query_cache], [local key caching]) # # Conditional stuff # AC_ARG_ENABLE([allsymbols], AS_HELP_STRING([--enable-allsymbols], [export internal-use symbols for better test coverage])) AM_CONDITIONAL(ALL_SYMBOLS, [test x"$enable_allsymbols" = x"yes"]) # the AM_CONDITIONAL and AC_DEFINE for USE_ARLIB are farther below, # after the Darwin checks AC_ARG_ENABLE([debug], AS_HELP_STRING([--enable-debug], [produce debugging binaries and libraries]), AS_IF([test "x$enable_debug" = x"yes"], [ LIBOPENDKIM_FEATURE_STRING="$LIBOPENDKIM_FEATURE_STRING debug" [[CFLAGS=`echo $CFLAGS | sed 's/ -O[1-9s]*//g'`]] ]) ) AM_CONDITIONAL([DEBUG], [test x"$enable_debug" = x"yes"]) # # gnutls # AC_ARG_WITH([gnutls], AS_HELP_STRING([--with-gnutls], [location of GnuTLS includes and library]), [gtpath="$withval"], [gtpath="no"]) gnutls_found="no" if test \( x"$gtpath" = x"auto" -o x"$gtpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([GNUTLS], [gnutls >= 2.11.7], [gnutls_found="pkg-config"], [gnutls_found="auto" AC_MSG_WARN([pkg-config for GnuTLS not found, trying manual search...]) ]) elif test x"$gtpath" != x"no" then AC_MSG_NOTICE([checking for GnuTLS library and includes in $gtpath]) saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LIBS="$outer_LIBS -lgnutls $saved_LIBS" CPPFLAGS="-I$gtpath/include $saved_CPPFLAGS" CFLAGS="$saved_CFLAGS" LDFLAGS="-L$gtpath/lib $saved_LDFLAGS" AC_CHECK_HEADERS([gnutls/gnutls.h], , AC_MSG_ERROR([required GnuTLS header not found])) AC_SEARCH_LIBS([gnutls_global_init], [gnutls], , AC_MSG_ERROR([libgnutls not found]), [-lnettle -lgmp -ldl]) LIBCRYPTO_CPPFLAGS="-I$gtpath/include" LIBCRYPTO_LIBDIRS="-L$gtpath/lib" LIBCRYPTO_LIBS="-lgnutls" CFLAGS="$saved_CFLAGS" CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" gnutls_found="yes" fi if test x"$gnutls_found" = x"pkg-config" then LIBCRYPTO_CPPFLAGS="$GNUTLS_CFLAGS" LIBCRYPTO_LDFLAGS="" LIBCRYPTO_LIBS="$GNUTLS_LIBS" gnutls_found="yes" fi if test x"$gtpath" = x"yes" -a x"$gnutls_found" = x"auto" then gcdirs="/usr/local /usr" for d in $gcdirs do AC_MSG_NOTICE([checking for GnuTLS library and includes in $d]) saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LIBS="$outer_LIBS -lgnutls $saved_LIBS" CPPFLAGS="-I$d/include $saved_CPPFLAGS" CFLAGS="$saved_CFLAGS" LDFLAGS="$outer_LDFLAGS -L$d/lib $saved_LDFLAGS" gnutls_h_found="no" gnutls_lib_found="no" AC_CHECK_HEADERS([gnutls/gnutls.h], gnutls_h_found="yes") AC_SEARCH_LIBS([gnutls_global_init], [gnutls], gnutls_lib_found="yes", , [-lnettle -lgmp]) CFLAGS="$saved_CFLAGS" CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$gnutls_h_found" = x"yes" -a \ x"$gnutls_lib_found" = x"yes" then LIBCRYPTO_CPPFLAGS="-I$d/include" LIBCRYPTO_LIBDIRS="-L$d/lib" LIBCRYPTO_LIBS="-lgnutls" gnutls_found="yes" AC_MSG_NOTICE(libgnutls found in $d) break else AC_MSG_NOTICE(not found in $d) fi done if test x"$gnutls_found" != x"yes" then AC_MSG_ERROR([GnuTLS not found]) fi fi if test x"$gnutls_found" = x"yes" then AC_DEFINE(USE_GNUTLS, 1, [Define to 1 to use libgnutls instead of OpenSSL.]) saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$LIBCRYPTO_CPPFLAGS $saved_CPPFLAGS" versioncheck=' #include #if GNUTLS_VERSION_NUMBER < 0x020b07 # error GnuTLS 2.11.7 or later required #endif int main() { return 0; }' AC_MSG_CHECKING([your GnuTLS version]) AC_LINK_IFELSE([AC_LANG_SOURCE([$versioncheck])], AC_MSG_RESULT(ok), AC_MSG_FAILURE([GnuTLS must be at least version 2.11.7])) sha256check=' #include int main() { int x = GNUTLS_DIG_SHA256; }' AC_MSG_CHECKING([whether your GnuTLS supports SHA256]) AC_LINK_IFELSE([AC_LANG_SOURCE([$sha256check])], AC_MSG_RESULT(yes) AC_DEFINE([HAVE_SHA256], 1, [Define to 1 if your crypto library has SHA256 support]), AC_MSG_WARN([SHA256 is required for DKIM but is not supported with your version of GnuTLS])) CPPFLAGS="$saved_CPPFLAGS" fi AM_CONDITIONAL([USE_GNUTLS], [test x"$gnutls_found" = x"yes"]) # # OpenSSL # AC_ARG_WITH([openssl], AS_HELP_STRING([--with-openssl], [location of OpenSSL includes and library]), [sslpath="$withval"], [sslpath="auto"]) openssl_found="no" if test x"$gnutls_found" = x"yes" then sslpath="skip" openssl_found="skip" fi if test \( "$sslpath" = "auto" -o x"$sslpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([LIBCRYPTO], [openssl >= 0.9.7], [openssl_found="yes"], [openssl_found="no" AC_MSG_WARN([pkg-config for openssl not found, trying manual search...]) ]) elif test "$sslpath" != "auto" -a x"$sslpath" != x"yes" then AC_MSG_CHECKING([for OpenSSL includes]) if test -f $sslpath/include/openssl/opensslv.h then LIBCRYPTO_CPPFLAGS="-I$sslpath/include" LIBCRYPTO_CFLAGS="" LIBCRYPTO_LIBDIRS="-L$sslpath/lib" LIBCRYPTO_LIBS="-lssl -lcrypto" openssl_found=yes AC_MSG_RESULT([$sslpath]) else AC_MSG_RESULT([no]) fi fi if test x"$openssl_found" = x"no" then AC_MSG_CHECKING([for OpenSSL library and includes]) ssldirs="/usr/local/ssl /usr/local /usr/sfw /opt/local /usr" if test "$sslpath" = "auto" -o "$sslpath" = "yes" then for d in $ssldirs do if test -f $d/include/openssl/opensslv.h then sslpath=$d openssl_found=yes break fi done fi case "$sslpath" in no) AC_MSG_ERROR([OpenSSL is required]) ;; auto) AC_MSG_ERROR([OpenSSL not found]) ;; */*) AC_MSG_RESULT([$sslpath]) ;; *) AC_MSG_ERROR([OpenSSL not found]) ;; esac LIBCRYPTO_CPPFLAGS="-I$sslpath/include" LIBCRYPTO_CFLAGS="" LIBCRYPTO_LIBDIRS="-L$sslpath/lib" LIBCRYPTO_LIBS="-lssl -lcrypto" fi if test x"$openssl_found" = x"yes" then saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LIBS="$outer_LIBS $LIBCRYPTO_LIBS $saved_LIBS" CPPFLAGS="$LIBCRYPTO_CPPFLAGS $saved_CPPFLAGS" CFLAGS="$LIBCRYPTO_CFLAGS $saved_CFLAGS" LDFLAGS="$outer_LDFLAGS $LIBCRYPTO_LIBDIRS $saved_LDFLAGS" AC_CHECK_HEADERS([openssl/bio.h openssl/conf.h openssl/crypto.h openssl/err.h openssl/evp.h openssl/md5.h openssl/opensslv.h openssl/pem.h openssl/rsa.h openssl/sha.h openssl/ssl.h], , AC_MSG_ERROR([required OpenSSL header not found])) # -ldl is needed to assist with compilation of static openssl libraries. # It appears to need dl for opening engine plugins. It fails at load # time It also fails to build on FreeBSD if enabled by default. AC_SEARCH_LIBS([ERR_peek_error], [crypto], , AC_MSG_ERROR([libcrypto not found])) AC_LINK_IFELSE( [AC_LANG_PROGRAM([[#include ]], [[SSL_library_init();]])], [od_have_ossl="yes";], [od_have_ossl="no";]) if test x"$od_have_ossl" = x"no" then if test x"$enable_shared" = x"yes" then AC_MSG_ERROR([Cannot build shared opendkim against static openssl libraries. Configure with --disable-shared to get this working or obtain a shared libssl library for opendkim to use.]) fi LIBCRYPTO_LIBS="$LIBCRYPTO_LIBS -ldl" AC_SEARCH_LIBS([SSL_library_init], [ssl], , AC_MSG_ERROR([libssl not found]), [-ldl]) fi AC_CHECK_DECL([EVP_PKEY_ED25519], AC_DEFINE([HAVE_ED25519], 1, [Define to 1 if your crypto library has ED25519 support]), , [ #include #include ]) AC_CHECK_DECL([SHA256_DIGEST_LENGTH], AC_DEFINE([HAVE_SHA256], 1, [Define to 1 if your crypto library has SHA256 support]), AC_MSG_WARN([SHA256 is required for DKIM but is not supported with your version of OpenSSL]), [ #include #include ]) CFLAGS="$saved_CFLAGS" CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" fi AC_SUBST(LIBCRYPTO_CFLAGS) AC_SUBST(LIBCRYPTO_CPPFLAGS) AC_SUBST(LIBCRYPTO_LIBDIRS) AC_SUBST(LIBCRYPTO_LIBS) # # libmilter # AC_MSG_CHECKING([for milter library and includes]) AC_ARG_WITH([milter], AS_HELP_STRING([--with-milter], [location of milter includes and library]), [milterpath="$withval"], [milterpath="auto"]) if test x"$enable_filter" = x"no" then milterpath="no" fi if test "$milterpath" = "auto" -o "$milterpath" = "yes" then milterdirs="/usr/local /opt/local /usr" for d in $milterdirs do if test -f $d/include/libmilter/mfapi.h then milterpath=$d break fi done fi case "$milterpath" in no) if test x"$enable_filter" = x"yes" then AC_MSG_ERROR([milter is required]) fi AC_MSG_RESULT(disabled) ;; auto) AC_MSG_ERROR([milter not found]) ;; */*) if ! test -f $milterpath/include/libmilter/mfapi.h then AC_MSG_ERROR([milter includes not found at $milterpath]) fi AC_MSG_RESULT([$milterpath]) ;; *) AC_MSG_ERROR([milter not found]) ;; esac LIBMILTER_INCDIRS="" LIBMILTER_LIBDIRS="" LIBMILTER_LIBS="" if test x"$milterpath" != x"no" then LIBMILTER_INCDIRS="-I$milterpath/include" saved_CC="$CC" saved_CFLAGS="$CFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" CC="$PTHREAD_CC" LIBS="$outer_LIBS $PTHREAD_LIBS $saved_LIBS" CPPFLAGS="$LIBMILTER_INCDIRS $saved_CPPFLAGS" CFLAGS="$PTHREAD_CFLAGS $saved_CFLAGS" LDFLAGS="$outer_LDFLAGS $PTHREAD_CFLAGS $saved_LDFLAGS" breakloop="no" for d in lib lib64 lib/libmilter do unset ac_cv_search_smfi_register LDFLAGS="$outer_LDFLAGS $PTHREAD_CFLAGS -L$milterpath/$d $saved_LDFLAGS" AC_SEARCH_LIBS([smfi_register], [milter], [ LIBMILTER_LIBDIRS="-L$milterpath/$d" LIBMILTER_LIBS="-lmilter" breakloop="yes" ]) AC_CHECK_FUNC([smfi_insheader], AC_DEFINE([HAVE_SMFI_INSHEADER], 1, [Define if libmilter has smfi_insheader()])) AC_CHECK_FUNC([smfi_opensocket], AC_DEFINE([HAVE_SMFI_OPENSOCKET], 1, [Define if libmilter has smfi_opensocket()])) AC_CHECK_FUNC([smfi_progress], AC_DEFINE([HAVE_SMFI_PROGRESS], 1, [Define if libmilter has smfi_progress()])) AC_CHECK_FUNC([smfi_setsymlist], AC_DEFINE([HAVE_SMFI_SETSYMLIST], 1, [Define if libmilter has smfi_setsymlist()])) AC_CHECK_FUNC([smfi_version], AC_DEFINE([HAVE_SMFI_VERSION], 1, [Define if libmilter has smfi_version()])) if test x"$breakloop" = x"yes" then break fi done if test x"$LIBMILTER_LIBDIRS" = x"" then AC_MSG_ERROR([libmilter not found]) fi CC="$saved_CC" CPPFLAGS="$saved_CPPFLAGS" CFLAGS="$saved_CFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" fi AC_SUBST(LIBMILTER_INCDIRS) AC_SUBST(LIBMILTER_LIBDIRS) AC_SUBST(LIBMILTER_LIBS) # # librrd # AC_ARG_WITH([librrd], AS_HELP_STRING([--with-librrd], [location of librrd includes and library]), [librrdpath="$withval"], [librrdpath="no"]) librrd_found="no" if test x"$enable_reprrd" = x"yes" -a x"$librrdpath" = x"no" then librrdpath="auto" fi if test \( x"$librrdpath" = x"auto" -o x"$librrdpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([RRDTOOL], [librrd], [ librrd_found="yes" ], [ AC_MSG_WARN([pkg-config for rrdtool not found, trying manual search...]) ]) fi if test \( x"$librrdpath" = x"auto" -o x"$librrdpath" = x"yes" \) -a x"$librrd_found" = x"no" then AC_MSG_CHECKING([for librrd]) librrddirs="/usr /usr/local" for d in $librrddirs do if test -f $d/include/rrd.h then librrdpath=$d AC_MSG_RESULT($d) RRDTOOL_CFLAGS="-I$librrdpath/include" RRDTOOL_LIBS="-L$librrdpath/lib -lrrd" librrd_found="yes" break fi done if test x"$RRDTOOL_LIBS" = x"" then AC_MSG_ERROR([not found]) fi elif test x"$librrdpath" != x"no" -a x"$librrd_found" = x"no" then AC_MSG_CHECKING([for librrd]) if test -f $librrdpath/include/rrd.h then AC_MSG_RESULT([$librrdpath]) RRDTOOL_CFLAGS="-I$librrdpath/include" RRDTOOL_LIBS="-L$librrdpath/lib -lrrd" librrd_found="yes" else AC_MSG_ERROR([not found at $librrdpath]) fi fi if test x"$librrdpath" = x"no" -o x"$librrd_found" = x"no" then RRDTOOL_CFLAGS="" RRDTOOL_LIBS="" AC_SUBST([LIBRRD_MANNOTICE], "(Not enabled for this installation.)" ) else AC_DEFINE([USE_RRD], 1, [use RRD library]) AC_SUBST([LIBRRD_MANNOTICE], "" ) fi AM_CONDITIONAL(USE_RRD, test x"$librrdpath" != x"no") AC_SUBST(RRDTOOL_CFLAGS) AC_SUBST(RRDTOOL_LIBS) # # libmemcached # AC_ARG_WITH([libmemcached], AS_HELP_STRING([--with-libmemcached], [location of libmemcached includes and library]), [libmcdpath="$withval"], [libmcdpath="no"]) libmemcache_found="no" if test \( x"$libmcdpath" = x"auto" -o x"$libmcdpath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([LIBMEMCACHED], [libmemcached >= 0.36], [ libmemcache_found="yes" LIBMEMCACHED_INCDIRS="$LIBMEMCACHED_CFLAGS" ], [ AC_MSG_WARN([pkg-config for libmemcached not found, trying manual search...]) ]) fi if test \( x"$libmcdpath" = x"auto" -o x"$libmcdpath" = x"yes" \) -a x"$libmemcache_found" = x"no" then AC_MSG_CHECKING([for libmemcached]) libmcddirs="/usr /usr/local" for d in $libmcddirs do if test -f $d/include/libmemcached/memcached.h then libmcdpath=$d AC_MSG_RESULT($d) LIBMEMCACHED_INCDIRS="-I$libmcdpath/include" LIBMEMCACHED_LIBDIRS="-L$libmcdpath/lib" LIBMEMCACHED_LIBS="-lmemcached" libmemcache_found="yes" break fi done if test x"$LIBMEMCACHED_LIBS" = x"" then AC_MSG_ERROR([not found]) fi elif test x"$libmcdpath" != x"no" -a x"$libmemcache_found" = x"no" then AC_MSG_CHECKING([for libmemcached]) if test -f $libmcdpath/include/libmemcached/memcached.h then AC_MSG_RESULT([$libmcdpath]) LIBMEMCACHED_INCDIRS="-I$libmcdpath/include" LIBMEMCACHED_LIBDIRS="-L$libmcdpath/lib" LIBMEMCACHED_LIBS="-lmemcached" libmemcache_found="yes" else AC_MSG_ERROR([not found at $libmcdpath]) fi fi # confirm memcached_return_t is defined if test x"$libmemcache_found" = x"yes" then saved_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $LIBMEMCACHED_INCDIRS" AC_MSG_CHECKING([for memcached_return_t]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include int main() { memcached_return_t x; return 0; } ])], AC_MSG_RESULT([ok]), AC_MSG_ERROR([libmemcached version 0.36 or later required])) fi if test x"$libmcdpath" = x"no" -o x"$libmemcache_found" = x"no" then LIBMEMCACHED_INCDIRS="" LIBMEMCACHED_LIBDIRS="" LIBMEMCACHED_LIBS="" AC_SUBST([LIBMEMCACHED_MANNOTICE], "(Not enabled for this installation.)" ) else AC_DEFINE([USE_LIBMEMCACHED], 1, [use memcache query library]) AC_SUBST([LIBMEMCACHED_MANNOTICE], "" ) fi AM_CONDITIONAL(USE_LIBMEMCACHED, test x"$libmcdpath" != x"no") AC_SUBST(LIBMEMCACHED_INCDIRS) AC_SUBST(LIBMEMCACHED_LIBDIRS) AC_SUBST(LIBMEMCACHED_LIBS) # # libunbound # AC_ARG_WITH([unbound], AS_HELP_STRING([--with-unbound], [location of Unbound includes and library]), [unboundpath="$withval"], [unboundpath="no"]) if test x"$unboundpath" = x"yes" then AC_MSG_CHECKING([for libunbound]) unbounddirs="/usr /usr/local" for d in $unbounddirs do if test -f $d/include/unbound.h then unboundpath=$d AC_MSG_RESULT($d) LIBUNBOUND_INCDIRS="-I$unboundpath/include" LIBUNBOUND_LIBDIRS="-L$unboundpath/lib" LIBUNBOUND_LIBS="-lunbound" break fi done if test x"$LIBUNBOUND_LIBS" = x"" then AC_MSG_ERROR([not found]) fi elif test x"$unboundpath" = x"no" then LIBUNBOUND_INCDIRS="" LIBUNBOUND_LIBDIRS="" LIBUNBOUND_LIBS="" else AC_MSG_CHECKING([for libunbound]) if test -f $unboundpath/include/unbound.h then AC_MSG_RESULT([$unboundpath]) LIBUNBOUND_INCDIRS="-I$unboundpath/include" LIBUNBOUND_LIBDIRS="-L$unboundpath/lib" LIBUNBOUND_LIBS="-lunbound" else AC_MSG_ERROR([not found at $unboundpath]) fi fi if test x"$unboundpath" = x"no" then AC_SUBST([UNBOUND_MANNOTICE], "(Not enabled for this installation.)" ) else AC_DEFINE([USE_UNBOUND], 1, [use unbound DNSSEC library for DNS]) AC_SUBST([UNBOUND_MANNOTICE], "" ) fi AM_CONDITIONAL(USE_UNBOUND, test x"$unboundpath" != x"no") AC_SUBST(LIBUNBOUND_INCDIRS) AC_SUBST(LIBUNBOUND_LIBDIRS) AC_SUBST(LIBUNBOUND_LIBS) # unbound also needs ldns AC_ARG_WITH([ldns], AS_HELP_STRING([--with-ldns], [location of ldns includes and library]), [ldnspath="$withval"], [ldnspath="no"]) LIBLDNS_LIBS="" LIBLDNS_LIBDIRS="" if test x"$ldnspath" = x"yes" then ldns_found="no" ldnsdirs="/usr /usr/local" for d in $ldnsdirs do unset ac_cv_search_ldns_rr_new saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" AC_SEARCH_LIBS([ldns_rr_new], [ldns], ldns_found="yes") LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$ldns_found" = x"yes" then LIBLDNS_LIBDIRS="-L$d/lib" LIBLDNS_LIBS="-lldns" break fi done if test x"$LIBLDNS_LIBS" = x"" then AC_MSG_ERROR([libldns not found]) fi elif test x"$ldnspath" != x"no" then ldns_found="no" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" AC_SEARCH_LIBS([ldns_rr_new], [ldns], ldns_found="yes") LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$ldns_found" = x"yes" then LIBLDNS_LIBDIRS="-L$d/lib" LIBLDNS_LIBS="-lldns" break else AC_MSG_ERROR(libldns not found in $d) fi fi AC_SUBST(LIBLDNS_LIBDIRS) AC_SUBST(LIBLDNS_LIBS) # unbound may also need libevent AC_ARG_WITH([libevent], AS_HELP_STRING([--with-libevent], [location of libevent includes and library]), [libeventpath="$withval"], [libeventpath="no"]) LIBEVENT_LIBS="" LIBEVENT_LIBDIRS="" if test x"$libevent" = x"yes" then libevent_found="no" libeventdirs="/usr /usr/local" for d in $libeventdirs do unset ac_cv_search_libevent_rr_new saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" AC_SEARCH_LIBS([evutil_vsnprintf], [event], libevent_found="yes") LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$libevent_found" = x"yes" then LIBEVENT_LIBDIRS="-L$d/lib" LIBEVENT_LIBS="-levent" break fi done if test x"$LIBEVENT_LIBS" = x"" then AC_MSG_ERROR([libevent not found]) fi elif test x"$libeventpath" != x"no" then libevent_found="no" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" LDFLAGS="$outer_LDFLAGS -L$d/lib $LDFLAGS" LIBS="$outer_LIBS" AC_SEARCH_LIBS([evutil_vsnprintf], [event], libevent_found="yes") LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" if test x"$libevent_found" = x"yes" then LIBEVENT_LIBDIRS="-L$d/lib" LIBEVENT_LIBS="-levent" break else AC_MSG_ERROR(libevent not found in $d) fi fi AC_SUBST(LIBEVENT_LIBDIRS) AC_SUBST(LIBEVENT_LIBS) # # libtre # AC_ARG_WITH([tre], AS_HELP_STRING([--with-tre], [location of TRE includes and library]), [trepath="$withval"], [trepath="auto"]) tre_found="no" LIBTRE_CPPFLAGS="" LIBTRE_LIBS="" if test x"$enable_diffheaders" != x"yes" then trepath="no" fi if test \( x"$trepath" = x"auto" -o x"$trepath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([LIBTRE], [tre >= 0.8.0], [tre_found="yes"], [ PKG_CHECK_MODULES([LIBTRE], [tre >= 0.7.5], [ tre_found="yes" AC_DEFINE([TRE_PRE_080], 1, [version of libtre is older than 0.8.0]) ],[ tre_found="no" AC_MSG_WARN([pkg-config for libtre >= 0.7.5 not found, trying manual search...]) ]) ]) fi if test x"$tre_found" = x"no" -a x"$trepath" != x"no" then AC_MSG_CHECKING([for libtre]) if test x"$trepath" != x"auto" -a x"$trepath" != x"yes" then if test -f "$trepath/include/tre/tre.h" then tre_found="yes" AC_MSG_RESULT($trepath) LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" elif test -f "$trepath/include/tre/regex.h" then tre_found="yes" AC_MSG_RESULT([$trepath (old version)]) AC_DEFINE([TRE_PRE_080], 1, [version of libtre is older than 0.8.0]) LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" else AC_MSG_ERROR("not found at $trepath") fi else tredirs="/usr /usr/local" for d in $tredirs do if test -f $d/include/tre/tre.h then trepath=$d tre_found="yes" AC_MSG_RESULT($d) LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" break elif test -f $d/include/tre/regex.h then trepath=$d tre_found="yes" AC_MSG_RESULT([$d (old version)]) AC_DEFINE([TRE_PRE_080], 1, [version of libtre is older than 0.8.0]) LIBTRE_CPPFLAGS="-I$trepath/include" LIBTRE_LIBS="-L$trepath/lib -ltre" break fi done if test x"$tre_found" != x"yes" then AC_MSG_RESULT([not found]) AC_MSG_ERROR([cannot use diffheaders without TRE library]) fi fi fi if test x"$enable_diffheaders" = x"yes" -a x"$tre_found" = x"yes" then AC_DEFINE([USE_TRE], 1, [tre regex library found]) fi AM_CONDITIONAL([USE_TRE], [test x"$tre_found" != x"no"]) AC_SUBST([LIBTRE_CPPFLAGS]) AC_SUBST([LIBTRE_LIBS]) # # liblua # AC_ARG_WITH([lua], AS_HELP_STRING([--with-lua], [location of Lua includes and library]), [luapath="$withval"], [luapath="no"]) LIBLUA_INCDIRS="" LIBLUA_LIBDIRS="" LIBLUA_LIBS="" lua_found="no" if test \( x"$luapath" = x"auto" -o x"$luapath" = x"yes" \) -a x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([LIBLUA], [lua5.1], [ lua_found="yes" LIBLUA_INCDIRS="$LIBLUA_CFLAGS" ], [AC_MSG_WARN([pkg-config for Lua not found, trying manual search...])]) fi if test \( x"$luapath" = x"yes" -o x"$luapath" = x"auto" \) -a x"$lua_found" = x"no" then AC_MSG_CHECKING([for Lua]) luadirs="/usr /usr/local" for d in $luadirs do if test -f $d/include/lua51/lua.h then AC_MSG_RESULT($d) LIBLUA_INCDIRS="-I$d/include/lua51" LIBLUA_LIBDIRS="-L$d/lib/lua51" LIBLUA_LIBS="-llua -lm" AC_SEARCH_LIBS([dlopen], [dl]) AC_DEFINE([USE_LUA], 1, [support for Lua scripting]) AC_SUBST([LUA_MANNOTICE], "") lua_found="yes" break elif test -f $d/include/lua52/lua.h then AC_MSG_RESULT($d) LIBLUA_INCDIRS="-I$d/include/lua52" LIBLUA_LIBDIRS="-L$d/lib/lua52" LIBLUA_LIBS="-llua -lm" AC_SEARCH_LIBS([dlopen], [dl]) AC_DEFINE([USE_LUA], 1, [support for Lua scripting]) AC_SUBST([LUA_MANNOTICE], "") lua_found="yes" break elif test -f $d/include/lua5.1/lua.h then AC_MSG_RESULT($d) LIBLUA_INCDIRS="-I$d/include/lua5.1" LIBLUA_LIBDIRS="-L$d/lib" LIBLUA_LIBS="-llua5.1 -lm" AC_SEARCH_LIBS([dlopen], [dl]) AC_DEFINE([USE_LUA], 1, [support for Lua scripting]) AC_SUBST([LUA_MANNOTICE], "") lua_found="yes" break elif test -f $d/include/lua5.2/lua.h then AC_MSG_RESULT($d) LIBLUA_INCDIRS="-I$d/include/lua5.2" LIBLUA_LIBDIRS="-L$d/lib" LIBLUA_LIBS="-llua5.2 -lm" AC_SEARCH_LIBS([dlopen], [dl]) AC_DEFINE([USE_LUA], 1, [support for Lua scripting]) AC_SUBST([LUA_MANNOTICE], "") lua_found="yes" break elif test -f $d/include/lua.h then AC_MSG_RESULT($d) LIBLUA_INCDIRS="-I$d/include" LIBLUA_LIBDIRS="-L$d/lib" LIBLUA_LIBS="-llua -lm" AC_SEARCH_LIBS([dlopen], [dl]) lua_found="yes" break fi done if test x"$LIBLUA_LIBS" = x"" then LIBLUA_INCDIRS="" LIBLUA_LIBDIRS="" LIBLUA_LIBS="" AC_MSG_ERROR(not found) else lua_found="yes" fi fi if test x"$luapath" != x"yes" -a x"$luapath" != x"auto" -a x"$luapath" != x"no" then AC_MSG_CHECKING([for Lua]) if test -f $luapath/include/lua51/lua.h then AC_MSG_RESULT($luapath) LIBLUA_INCDIRS="-I$luapath/include/lua51" LIBLUA_LIBDIRS="-L$luapath/lib/lua51" LIBLUA_LIBS="-llua -lm" AC_SEARCH_LIBS([dlopen], [dl]) lua_found="yes" elif test -f $luapath/include/lua52/lua.h then AC_MSG_RESULT($luapath) LIBLUA_INCDIRS="-I$luapath/include/lua52" LIBLUA_LIBDIRS="-L$luapath/lib/lua52" LIBLUA_LIBS="-llua -lm" AC_SEARCH_LIBS([dlopen], [dl]) lua_found="yes" elif test -f $luapath/include/lua5.1/lua.h then AC_MSG_RESULT($luapath) LIBLUA_INCDIRS="-I$luapath/include/lua5.1" LIBLUA_LIBDIRS="-L$luapath/lib" LIBLUA_LIBS="-llua5.1 -lm" AC_SEARCH_LIBS([dlopen], [dl]) lua_found="yes" elif test -f $luapath/include/lua5.2/lua.h then AC_MSG_RESULT($luapath) LIBLUA_INCDIRS="-I$luapath/include/lua5.2" LIBLUA_LIBDIRS="-L$luapath/lib" LIBLUA_LIBS="-llua5.2 -lm" AC_SEARCH_LIBS([dlopen], [dl]) lua_found="yes" elif test -f $luapath/include/lua.h then AC_MSG_RESULT($luapath) LIBLUA_INCDIRS="-I$luapath/include" LIBLUA_LIBDIRS="-L$luapath/lib" LIBLUA_LIBS="-llua -lm" AC_SEARCH_LIBS([dlopen], [dl]) lua_found="yes" else AC_MSG_ERROR(not found at $luapath) fi fi if test x"$lua_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$outer_CPPFLAGS $LIBLUA_INCDIRS" AC_MSG_CHECKING([Lua version]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 # error Lua version 5.1 or later is required #endif int main() { return 0; } ])], AC_MSG_RESULT([ok]), AC_MSG_ERROR([Lua version 5.1 or later required])) CPPFLAGS="$saved_CPPFLAGS" AC_DEFINE([USE_LUA], 1, [support for Lua scripting]) AC_SUBST([LUA_MANNOTICE], "") else AC_SUBST([LUA_MANNOTICE], "(Not enabled for this installation.)") fi AM_CONDITIONAL(LUA, test x"$lua_found" = x"yes") AC_SUBST(LIBLUA_INCDIRS) AC_SUBST(LIBLUA_LIBDIRS) AC_SUBST(LIBLUA_LIBS) if test x"$enable_lua_only_signing" = x"yes" -a x"$lua_found" != x"yes" then AC_MSG_ERROR([--enable-lua_only_signing requires Lua support]) fi if test x"$enable_statsext" = x"yes" -a x"$lua_found" != x"yes" then AC_MSG_ERROR([--enable-statsext requires Lua support]) fi if test x"$enable_rbl" = x"yes" -a x"$lua_found" != x"yes" then AC_MSG_ERROR([--enable-rbl requires Lua support]) fi AC_ARG_WITH([sql-backend], AS_HELP_STRING([--with-sql-backend], [selection of SQL backend in use]), [SQL_BACKEND="$withval"], [SQL_BACKEND="mysql"]) AC_SUBST(SQL_BACKEND) AC_DEFINE_UNQUOTED(SQL_BACKEND, "$SQL_BACKEND", [default SQL back-end]) # # libodbx # AC_ARG_WITH([odbx], AS_HELP_STRING([--with-odbx], [location of OpenDBX includes and library]), [odbxpath="$withval"], [odbxpath="no"]) odbx_found="no" LIBODBX_CPPFLAGS="" LIBODBX_CFLAGS="" LIBODBX_LDFLAGS="" LIBODBX_LIBS="" if test \( x"$odbxpath" = x"auto" -o x"$odbxpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([LIBODBX], [opendbx >= 1.3.7], [odbx_found="yes"], [ odbx_found="no" AC_MSG_WARN([pkg-config for libodbx not found, trying manual search...]) ]) fi if test x"$odbxpath" != x"no" -a x"$odbx_found" = x"no" then saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" if test x"$odbxpath" != x"auto" -a x"$odbxpath" != x"yes" then if test -f $odbxpath/include/odbx.h then LDFLAGS="$outer_LDFLAGS -L$odbxpath/lib" LIBS="$outer_LIBS" AC_SEARCH_LIBS(odbx_result_finish, opendbx, [ odbx_found="yes" LIBODBX_CPPFLAGS="-I$odbxpath/include" LIBODBX_LDFLAGS="-L$odbxpath/lib" LIBODBX_LIBS="$LIBS" ], [ AC_MSG_ERROR([opendbx not at least v1.3.7 at $odbxpath]) ], [-ldl]) else AC_MSG_ERROR([opendbx not found at $odbxpath]) fi else odbxdirs="/usr /usr/local" for d in $odbxdirs do if test -f $d/include/odbx.h then LDFLAGS="$outer_LDFLAGS -L$d/lib" LIBS="$outer_LIBS" AC_SEARCH_LIBS(odbx_result_finish, opendbx, [ odbxpath=$d odbx_found="yes" LIBODBX_CPPFLAGS="-I$d/include" LIBODBX_LDFLAGS="-L$d/lib" LIBODBX_LIBS="$LIBS" break ],[ AC_MSG_ERROR([opendbx not at least v1.3.7 at $d]) ], [-ldl] ) fi done if test x"$odbx_found" != x"yes" then AC_MSG_ERROR([opendbx not found]) fi fi LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" fi if test x"$odbx_found" = x"yes" then AC_DEFINE([USE_ODBX], 1, [ODBX support for datasets enabled]) else if test x"$enable_stats" = x"yes" then AC_MSG_WARN([opendbx is needed to import statistics into a SQL database - disabling opendkim-importstats and opendkim-spam]) fi fi AM_CONDITIONAL(USE_ODBX, test x"$odbx_found" = x"yes") AC_SUBST(LIBODBX_CPPFLAGS) AC_SUBST(LIBODBX_CFLAGS) AC_SUBST(LIBODBX_LDFLAGS) AC_SUBST(LIBODBX_LIBS) # # OpenLDAP # AC_ARG_WITH([openldap], AS_HELP_STRING([--with-openldap], [location of OpenLDAP includes and library]), [ldappath="$withval"], [ldappath="no"]) ldap_found="no" OPENLDAP_CPPFLAGS="" OPENLDAP_LIBS="" if test \( x"$ldappath" = x"auto" -o x"$ldappath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([OPENLDAP], [openldap >= 2.0.0], [ ldap_found="yes" OPENLDAP_CPPFLAGS="$OPENLDAP_CFLAGS" ], [ ldap_found="no" AC_MSG_WARN([pkg-config for openldap not found, trying manual search...]) ]) fi if test x"$ldappath" != x"no" -a x"$ldap_found" = x"no" then AC_MSG_CHECKING([for OpenLDAP]) if test x"$ldappath" != x"auto" -a x"$ldappath" != x"yes" then if test -f $ldappath/include/ldap.h then AC_MSG_RESULT($ldappath) ldap_found="yes" OPENLDAP_CPPFLAGS="-I$ldappath/include" OPENLDAP_LIBS="-L$ldappath/lib -lldap -llber" else AC_MSG_ERROR(not found at $ldappath) fi else ldapdirs="/usr /usr/local" for d in $ldapdirs do if test -f $d/include/ldap.h then ldappath=$d AC_MSG_RESULT($d) ldap_found="yes" OPENLDAP_CPPFLAGS="-I$ldappath/include" OPENLDAP_LIBS="-L$ldappath/lib -lldap -llber" break fi done fi if test x"$ldap_found" != x"yes" then AC_MSG_RESULT([no]) fi fi if test x"$ldap_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$outer_CPPFLAGS $OPENLDAP_CPPFLAGS" AC_MSG_CHECKING([OpenLDAP version]) AC_COMPILE_IFELSE([AC_LANG_SOURCE([ #include #if !defined(LDAP_API_VERSION) || LDAP_API_VERSION < 2004 # error OpenLDAP version 2.1.3 or later is required #endif int main() { return 0; } ])], AC_MSG_RESULT([ok]), AC_MSG_ERROR([OpenLDAP version 2.1.3 or later required])) CPPFLAGS="$saved_CPPFLAGS" AC_DEFINE([USE_LDAP], 1, [OpenLDAP support for datasets enabled]) fi AM_CONDITIONAL(USE_LDAP, test x"$ldap_found" = x"yes") AC_SUBST(OPENLDAP_CPPFLAGS) AC_SUBST(OPENLDAP_LIBS) # # SASL # AC_ARG_WITH([sasl], AS_HELP_STRING([--with-sasl], [location of SASL includes]), [saslpath="$withval"], [saslpath="auto"]) if test x"$ldap_found" != x"yes" then # disable sasl if we don't have ldap saslpath="no" fi sasl_found="no" if test \( x"$saslpath" = x"auto" -o x"$saslpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([SASL], [cyrussasl >= 2.1.0], [ sasl_found="yes" SASL_CPPFLAGS="$SASL_CFLAGS" ], [ sasl_found="no" AC_MSG_WARN([pkg-config for cyrussasl not found, trying manual search...]) ]) fi if test x"$saslpath" != x"no" -a x"$sasl_found" = x"no" then AC_MSG_CHECKING([for SASL]) if test x"$saslpath" != x"auto" -a x"$saslpath" != x"yes" then if test -f $saslpath/include/sasl/sasl.h then AC_MSG_RESULT($saslpath) sasl_found="yes" SASL_CPPFLAGS="-I$saslpath/include" else AC_MSG_ERROR(not found at $saslpath) fi else sasldirs="/usr /usr/local" for d in $sasldirs do if test -f $d/include/sasl/sasl.h then saslpath=$d AC_MSG_RESULT($d) sasl_found="yes" SASL_CPPFLAGS="-I$saslpath/include" break fi done fi if test x"$sasl_found" != x"yes" then AC_MSG_RESULT([no]) fi fi if test x"$sasl_found" = x"yes" then AC_DEFINE([USE_SASL], 1, [SASL support available]) fi AM_CONDITIONAL(USE_SASL, test x"$sasl_found" = x"yes") AC_SUBST(SASL_CPPFLAGS) # # libmdb # AC_ARG_WITH([lmdb], AS_HELP_STRING([--with-lmdb], [location of OpenLDAP MDB includes and library]), [mdbpath="$withval"], [mdbpath="no"]) mdb_found="no" LIBMDB_CPPFLAGS="" LIBMDB_LIBS="" if test x"$mdbpath" != x"no" -a x"$mdb_found" = x"no" then saved_ldflags="$LDFLAGS" saved_cflags="$CFLAGS" CFLAGS="$outer_CFLAGS -pthread" if test x"$mdbpath" != x"auto" -a x"$mdbpath" != x"yes" then if test -f $mdbpath/include/lmdb.h then LDFLAGS="$outer_LDFLAGS -L$mdbpath/lib $STRL_LIBS" AC_CHECK_LIB(lmdb, mdb_env_open, [ mdb_found="yes" LIBMDB_CPPFLAGS="-I$mdbpath/include" LIBMDB_LIBS="-L$mdbpath/lib -llmdb" ], [ AC_MSG_ERROR([lmdb not valid at $mdbpath]) ] ) else AC_MSG_ERROR([lmdb not found at $mdbpath]) fi else mdbdirs="/usr /usr/local" for d in $mdbdirs do if test -f $d/include/lmdb.h then LDFLAGS="$outer_LDFLAGS -L$d/lib $STRL_LIBS" AC_CHECK_LIB(lmdb, mdb_env_open, [ mdbpath=$d mdb_found="yes" LIBMDB_CPPFLAGS="-I$mdbpath/include" LIBMDB_LIBS="-L$mdbpath/lib -llmdb" break ] ) fi done if test x"$mdb_found" != x"yes" then AC_MSG_ERROR([lmdb not found]) fi fi LDFLAGS="$saved_ldflags" CFLAGS="$saved_cflags" fi if test x"$mdb_found" = x"yes" then AC_DEFINE([USE_MDB], 1, [OpenLDAP MDB support for datasets enabled]) fi AM_CONDITIONAL(USE_MDB, test x"$mdb_found" = x"yes") AC_SUBST(LIBMDB_CPPFLAGS) AC_SUBST(LIBMDB_LIBS) # # # libcurl, required by reputation # AC_ARG_WITH([libcurl], AS_HELP_STRING([--with-libcurl], [location of CURL includes and library]), [curlpath="$withval"], [curlpath="auto"]) CURL_CPPFLAGS="" CURL_LDFLAGS="" CURL_LIBS="" if test x"$enable_reputation" != x"yes" -a \ x"$curlpath" = x"auto" then curlpath="no" fi curl_found="no" if test \( x"$curlpath" = x"auto" -o x"$curlpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([CURL], [libcurl >= 7.12.0], [ curl_found="yes" CURL_CPPFLAGS="$CURL_CFLAGS" ], [ curl_found="no" AC_MSG_WARN([pkg-config for curl not found, trying manual search...]) ]) fi if test x"$curlpath" != x"no" -a x"$curl_found" = x"no" then AC_MSG_CHECKING([for CURL]) if test x"$curlpath" != x"auto" -a x"$curlpath" != x"yes" then if test -f $curlpath/include/curl/curl.h then AC_MSG_RESULT($curlpath) curl_found="yes" CURL_CPPFLAGS="-I$curlpath/include" CURL_LDFLAGS="$outer_LDFLAGS -L$curlpath/lib" CURL_LIBS="-lcurl" else AC_MSG_ERROR(not found at $curlpath) fi else curldirs="/usr /usr/local" for d in $curldirs do if test -f $d/include/curl/curl.h then curlpath=$d AC_MSG_RESULT($d) curl_found="yes" CURL_CPPFLAGS="-I$curlpath/include" CURL_LDFLAGS="$outer_LDFLAGS -L$curlpath/lib" CURL_LIBS="-lcurl" break fi done fi if test x"$curl_found" != x"yes" then AC_MSG_RESULT([no]) fi fi if test x"$curl_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" saved_LDFLAGS="$LDFLAGS" saved_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $CURL_CPPFLAGS" LDFLAGS="$LDFLAGS $CURL_LDFLAGS" LIBS="$LIBS $CURL_LIBS" AC_CHECK_FUNC([curl_easy_strerror], AC_DEFINE([HAVE_CURL_EASY_STRERROR], 1, [Define if libcurl has curl_easy_strerror()])) CPPFLAGS="$saved_CPPFLAGS" LDFLAGS="$saved_LDFLAGS" LIBS="$saved_LIBS" AC_SUBST([LIBCURL_MANNOTICE], "") else AC_SUBST([LIBCURL_MANNOTICE], "(Not enabled for this installation.)" ) fi AC_SUBST(CURL_CPPFLAGS) AC_SUBST(CURL_LDFLAGS) AC_SUBST(CURL_LIBS) if test x"$enable_reputation" = x"yes" -a \ x"$curl_found" != x"yes" then AC_MSG_ERROR([reputation requires curl]) fi # # reputation requires libjansson # AC_ARG_WITH([libjansson], AS_HELP_STRING([--with-libjansson], [location of jansson includes and library]), [janssonpath="$withval"], [janssonpath="auto"]) LIBJANSSON_CPPFLAGS="" LIBJANSSON_LDFLAGS="" LIBJANSSON_LIBS="" # if reputation is disabled, we don't need it if test x"$enable_reputation" != x"yes" -a \ x"$janssonpath" = x"auto" then janssonpath="no" fi jansson_found="no" if test \( x"$janssonpath" = x"auto" -o x"$janssonpath" = x"yes" \) -a \ x"$PKG_CONFIG" != x"" then PKG_CHECK_MODULES([LIBJANSSON], [jansson >= 2.2.1], [ jansson_found="yes" LIBJANSSON_CPPFLAGS="$LIBJANSSON_CFLAGS" LIBJANSSON_LIBS="$LIBJANSSON_LIBS" ], [ jansson_found="no" AC_MSG_WARN([pkg-config for libjansson not found, trying manual search...]) ]) fi if test x"$janssonpath" != x"no" -a x"$jansson_found" = x"no" then AC_MSG_CHECKING([for libjansson]) if test x"$janssonpath" != x"auto" -a x"$janssonpath" != x"yes" then if test -f $janssonpath/include/jansson.h then AC_MSG_RESULT($janssonpath) jansson_found="yes" LIBJANSSON_CPPFLAGS="-I$janssonpath/include" LIBJANSSON_LDFLAGS="-L$janssonpath/lib" LIBJANSSON_LIBS="-ljansson" else AC_MSG_ERROR(not found at $janssonpath) fi else janssondirs="/usr /usr/local" for d in $janssondirs do if test -f $d/include/jansson.h then janssonpath=$d AC_MSG_RESULT($d) jansson_found="yes" LIBJANSSON_CPPFLAGS="-I$janssonpath/include" LIBJANSSON_LDFLAGS="-L$janssonpath/lib" LIBJANSSON_LIBS="-ljansson" break fi done fi if test x"$jansson_found" != x"yes" then AC_MSG_RESULT([no]) fi fi AC_SUBST(LIBJANSSON_CPPFLAGS) AC_SUBST(LIBJANSSON_LDFLAGS) AC_SUBST(LIBJANSSON_LIBS) AM_CONDITIONAL(JANSSON, test x"$LIBJANSSON_LIBS" != x"") if test x"$enable_reputation" = x"yes" -a \ x"$jansson_found" != x"yes" then AC_MSG_ERROR([reputation requires libjansson]) fi if test x"$jansson_found" == x"yes" then AC_DEFINE(USE_JANSSON, 1, [use libjansson to parse REPUTE replies]) fi # # libdb # AC_ARG_WITH([db-incdir], AS_HELP_STRING([--with-db-incdir], [location of BerkeleyDB includes]), [bdb_incdir="$withval"], [bdb_incdir=""]) AC_ARG_WITH([db-libdir], AS_HELP_STRING([--with-db-libdir], [location of BerkeleyDB library]), [bdb_libdir="$withval"], [bdb_libdir=""]) AC_ARG_WITH([db-lib], AS_HELP_STRING([--with-db-lib], [name of BerkeleyDB library]), [bdb_lib="$withval"], [bdb_lib="db"]) AC_ARG_WITH([db], AS_HELP_STRING([--with-db], [location of BerkeleyDB includes and library]), [bdb="$withval"], [bdb="auto"]) LIBDB_INCDIRS="" LIBDB_LIBDIRS="" LIBDB_LIBS="" # was --with-db given with "yes" or a path? bdbrequested="no" if test x"$bdb" != x"no" -a x"$bdb" != x"auto" then bdbrequested="yes" fi if test x"$bdb_incdir" != x"" -o x"$bdb_libdir" != x"" -o x"$bdb_lib" != x"db" then bdbrequested="yes" fi rep_needs_bdb="no" if test x"$enable_reputation" = x"yes" -a x"$mdb_found" = x"no" then rep_needs_bdb="yes" fi AM_CONDITIONAL(USE_DB_OPENDKIM, test x"$enable_popauth" = x"yes" -o \ x"$rep_needs_bdb" = x"yes" -o \ x"$enable_ldap_caching" = x"yes" -o \ x"$bdbrequested" = x"yes") AM_CONDITIONAL(USE_DB_LIBOPENDKIM, test x"$enable_query_cache" = x"yes") # Is DB required based on --enables? if test x"$USE_DB_OPENDKIM_TRUE" = x"" -o \ x"$USE_DB_LIBOPENDKIM_TRUE" = x"" then bdbrequired="yes" else bdbrequired="no" fi # If --with-db wasn't specified and the --enables demand it, force "yes" if test x"$bdb" = x"auto" then if test x"$bdbrequired" = x"yes" then bdb="yes" else bdb="no" fi fi if test x"$bdb" != x"yes" -a x"$bdb" != x"no" then bdb_incdir=$bdb/include bdb_libdir=$bdb/lib bdb="yes" fi if test x"$bdb" = x"yes" then bdbdirs="/usr/local/BerkeleyDB /usr/local /usr" libdbfound="no" # look for db.h AC_MSG_CHECKING([for BerkeleyDB db.h]) if test x"$bdb_incdir" = x"" then for d in $bdbdirs do if test -f $d/include/db.h then bdb_incdir=$d/include AC_MSG_RESULT($bdb_incdir) break fi done if test x"$bdb_incdir" = x"" then AC_MSG_ERROR([not found]) fi elif ! test -f $bdb_incdir/db.h then AC_MSG_ERROR([not found in $bdb_incdir]) else AC_MSG_RESULT([$bdb_incdir]) fi # See if we can find a library by looking for db_create(), then # db_open(), then dbopen(). # # This can cause compilation problems if for example a db.h # and a libdb are found that aren't the same version, but it's # worth a shot in general. if test x"$bdb_libdir" = x"" then for d in $bdbdirs do saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LIBS="$LIBS" LDFLAGS="$LDFLAGS -L$d/lib" CPPFLAGS="$CPPFLAGS -I$bdb_incdir" LIBS="$outer_LIBS" if test x"$libdbfound" = x"no" then AC_SEARCH_LIBS([db_create], $bdb_lib, [libdbfound="yes"]) bdb_libdir=$d/lib fi if test x"$libdbfound" = x"no" then AC_SEARCH_LIBS([db_open], $bdb_lib, [libdbfound="yes"]) bdb_libdir=$d/lib fi if test x"$libdbfound" = x"no" then AC_SEARCH_LIBS([dbopen], $bdb_lib, [libdbfound="yes"]) bdb_libdir=$d/lib fi LDFLAGS="$saved_LDFLAGS" CPPFLAGS="$saved_CPPFLAGS" LIBS="$saved_LIBS" done else saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" saved_LIBS="$LIBS" LDFLAGS="$LDFLAGS -L$bdb_libdir" CPPFLAGS="$CPPFLAGS -I$bdb_incdir" LIBS="$outer_LIBS" if test x"$libdbfound" = x"no" then AC_SEARCH_LIBS([db_create], $bdb_lib, [libdbfound="yes"]) fi if test x"$libdbfound" = x"no" then AC_SEARCH_LIBS([db_open], $bdb_lib, [libdbfound="yes"]) fi if test x"$libdbfound" = x"no" then AC_SEARCH_LIBS([dbopen], $bdb_lib, [libdbfound="yes"]) fi LDFLAGS="$saved_LDFLAGS" CPPFLAGS="$saved_CPPFLAGS" LIBS="$saved_LIBS" fi if test x"$libdbfound" = x"no" then AC_MSG_ERROR([cannot find db_create, db_open or dbopen]) fi if test x"$bdb_incdir" != x"" then LIBDB_INCDIRS="-I$bdb_incdir" fi if test x"$bdb_libdir" != x"" then LIBDB_LIBDIRS="-L$bdb_libdir" LIBDB_LIBS="-l$bdb_lib" fi AC_DEFINE(USE_DB, 1, [enable support for SleepyCat/Berkeley DB libraries]) elif test x"$bdb" = x"no" then AC_MSG_CHECKING([for BerkeleyDB]) if test x"$bdbrequired" = x"yes" then AC_MSG_ERROR([disabled but required by requested features]) fi AC_MSG_RESULT([not required or disabled]) LIBDB_INCDIRS="" LIBDB_LIBDIRS="" LIBDB_LIBS="" fi if test x"$unboundpath" != x"no" -a x"$bdbrequired" = x"yes" then saved_LDFLAGS="$LDFLAGS" saved_CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS $LIBDB_LIBDIRS $LIBUNBOUND_LIBDIRS" CPPFLAGS="$CPPFLAGS $LIBDB_INCDIRS $LIBUNBOUND_INCDIRS" AC_CHECK_LIB([db], [log_file], AC_CHECK_LIB([unbound], [log_file], AC_MSG_ERROR([Cannot enable feature requiring BerkeleyDB with libunbound - both have log_file defined. Please use newer BerkeleyDB version]) ) ) LDFLAGS="$saved_LDFLAGS" CPPFLAGS="$saved_CPPFLAGS" fi AC_SUBST(LIBDB_INCDIRS) AC_SUBST(LIBDB_LIBDIRS) AC_SUBST(LIBDB_LIBS) LIBOPENDKIM_LIBS="$LIBCRYPTO_LIBS $LIBTRE_LIBS $LIBRESOLV" # This (below) is just for the pkg-config file opendkim.pc.in LIBOPENDKIM_LIBS_PKG="$LIBOPENDKIM_LIBS" LIBOPENDKIM_INC="$LIBCRYPTO_CPPFLAGS $LIBCRYPTO_CFLAGS $LIBTRE_CPPFLAGS" if test x"$USE_DB_LIBOPENDKIM_TRUE" = x"" then LIBOPENDKIM_INC="$LIBOPENDKIM_INC $LIBDB_INCDIRS" LIBOPENDKIM_LIBS_PKG="$LIBOPENDKIM_LIBS_PKG $LIBDB_LIBS" LIBOPENDKIM_LIBS="$LIBOPENDKIM_LIBS $LIBDB_LIBS" fi AC_SUBST(LIBOPENDKIM_LIBS) AC_SUBST(LIBOPENDKIM_LIBS_PKG) AC_SUBST(LIBOPENDKIM_INC) AC_DEFINE_UNQUOTED([LIBOPENDKIM_FEATURE_STRING], "$LIBOPENDKIM_FEATURE_STRING", [Feature string for printing]) # # setup for testing # AC_ARG_ENABLE([live-testing], AS_HELP_STRING([--disable-live-testing], [disable tests that require Internet access]), [live_tests="$enable_live_testing"], [live_tests="yes"]) AM_CONDITIONAL(LIVE_TESTS, test x"$live_tests" = x"yes") # # specify test socket # AC_ARG_WITH([test-socket], AS_HELP_STRING([--with-test-socket], [specify socket to use for all tests]), [testsocket="$withval"], [testsocket=""]) AM_CONDITIONAL(TEST_SOCKET, test x"$testsocket" != x"") if test x"$testsocket" != x"" then TESTSOCKET=$testsocket AC_SUBST(TESTSOCKET) fi # # Platform Specific Configuration # AC_CANONICAL_HOST case "$host" in *-darwin*) CPPFLAGS="$CPPFLAGS -DBIND_8_COMPAT -DDARWIN" if test x"$unboundpath" = x"no" then AC_MSG_ERROR("unbound required on Darwin") fi ;; esac # # Determine domainname for sample configs # AC_ARG_WITH([domain], AS_HELP_STRING([--with-domain], [name of the domain for signing - sets this in sample configuration files]), [ DOMAIN="$withval" ],[ AC_PATH_PROG(domainname, domainname) AS_IF([test x"$domainname" != x""], [DOMAIN=`$domainname`], ) AS_IF([test x"$DOMAIN" = x"" -o x"$DOMAIN" = x"(none)" ], [DOMAIN=example.com] ) ] ) AC_SUBST([DOMAIN]) AC_ARG_WITH([erlang], AS_HELP_STRING([--with-erlang], [location of Erlang includes and library]), [erlpath="$withval"], [erlpath="no"]) LIBERL_INCDIRS="" LIBERL_LIBDIRS="" LIBERL_LIBS="" erl_found="no" if test \( x"$erlpath" = x"yes" -o x"$erlpath" = x"auto" \) then AC_MSG_CHECKING([for Erlang]) b=`erl -noshell -eval 'io:format("~s~n", [[code:lib_dir()]]).' -s erlang halt` erlbase=`ls -d $b/erl_interface-* | tail -n1` AC_MSG_RESULT($erlbase) LIBERL_INCDIRS="-I$erlbase/include" LIBERL_LIBDIRS="-L$erlbase/lib" LIBERL_LIBS="-pthread -lerl_interface -lei" AC_DEFINE([USE_ERLANG], 1, [support for erlang access]) erl_found="yes" fi if test x"$erlpath" != x"yes" -a x"$erlpath" != x"auto" -a x"$erlpath" != x"no" then AC_MSG_CHECKING([for Erlang]) if test -f $erlpath/include/ei.h then AC_MSG_RESULT($erlpath) LIBERL_INCDIRS="-I$erlpath/include" LIBERL_LIBDIRS="-L$erlpath/lib" LIBERL_LIBS="-pthread -lerl_interface -lei" erl_found="yes" else AC_MSG_ERROR(not found at $erlpath) fi fi if test x"$erl_found" = x"yes" then saved_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$outer_CPPFLAGS $LIBERL_INCDIRS" AC_DEFINE([USE_ERLANG], 1, [support for Erlang access]) AC_SUBST([LIBERL_MANNOTICE], "") else AC_SUBST([LIBERL_MANNOTICE], "(Not enabled for this installation.)") fi AM_CONDITIONAL(ERLANG, test x"$erl_found" = x"yes") AC_SUBST(LIBERL_INCDIRS) AC_SUBST(LIBERL_LIBDIRS) AC_SUBST(LIBERL_LIBS) # # final command line tweaks # CPPFLAGS="$CPPFLAGS -DCONFIG_BASE=\\\"$sysconfdir\\\"" test "x$prefix" = xNONE && prefix=$ac_default_prefix SYSCONFDIR=`eval echo "$sysconfdir"` AC_SUBST([SYSCONFDIR]) # # for contrib/spec/opendkim.spec.in # installbin="no" specconfig="" specrequires="" specbuildrequires="" if test x"$enable_reputation" = x"yes" then specconfig="$specconfig --enable-reputation" specrequires="$specrequires libcurl" specbuildrequires="$specbuildrequires libcurl-devel jansson-devel" fi if test x"$enable_stats" = x"yes" then specconfig="$specconfig --enable-stats --with-odbx" specrequires="$specrequires libdb opendbx" specbuildrequires="$specbuildrequires libdb-devel opendbx-devel" fi if test x"$jansson_found" = x"yes" then # autobuild installbin="yes" specconfig="$specconfig --with-libjansson=$janssonpath" fi # opendkim-spam if test x"$enable_stats" = x"yes" -a x"$odbx_found" = x"yes" then installbin="yes" specconfig="$specconfig --enable-stats --with-odbx=$odbxpath" fi # miltertest if test x"$lua_found" = x"yes" then installbin="yes" specconfig="$specconfig --with-lua=$luapath" specrequries="$specrequires lua" specbuildrequries="$specbuildrequires lua-devel" fi SPECBINDIR="" if test x"$installbin" = x"yes" then SPECBINDIR="%{_bindir}/*" fi SPECCONFIGURE="$specconfig" if test x"$specrequires" = x"" then SPECREQUIRES="" else SPECREQUIRES="Requires:$specrequires" fi if test x"$specbuildrequires" = x"" then SPECBUILDREQUIRES="" else SPECBUILDREQUIRES="BuildRequires:$specbuildrequires" fi AC_SUBST(SPECBINDIR) AC_SUBST(SPECCONFIGURE) AC_SUBST(SPECREQUIRES) AC_SUBST(SPECBUILDREQUIRES) # # Finish up # AC_OUTPUT([ Makefile docs/Makefile autobuild/Makefile contrib/Makefile contrib/convert/Makefile contrib/docs/Makefile contrib/init/Makefile contrib/init/generic/Makefile contrib/init/redhat/Makefile contrib/init/redhat/opendkim contrib/init/redhat/opendkim-default-keygen contrib/init/solaris/Makefile contrib/ldap/Makefile contrib/lua/Makefile contrib/patches/Makefile contrib/repute/Makefile contrib/spec/Makefile contrib/spec/opendkim.spec contrib/stats/Makefile contrib/systemd/Makefile contrib/systemd/opendkim.service libopendkim/opendkim.pc libopendkim/Makefile libopendkim/docs/Makefile libopendkim/tests/Makefile librbl/rbl.pc librbl/Makefile libut/ut.pc libut/Makefile libvbr/vbr.pc libvbr/Makefile miltertest/Makefile opendkim/Makefile opendkim/opendkim.8 opendkim/opendkim-genkey opendkim/opendkim-genkey.8 opendkim/opendkim-genzone.8 opendkim/opendkim-lua.3 opendkim/opendkim-testkey.8 opendkim/opendkim-stats.8 opendkim/opendkim-testmsg.8 opendkim/opendkim.conf.5 opendkim/opendkim.conf.simple opendkim/opendkim.conf.simple-verify opendkim/opendkim-atpszone.8 opendkim/opendkim-spam.1 opendkim/tests/Makefile stats/Makefile stats/opendkim-importstats.8 stats/opendkim-expire stats/opendkim-expire.8 stats/opendkim-gengraphs stats/opendkim-gengraphs.8 stats/opendkim-genstats stats/opendkim-genstats.8 stats/opendkim-reportstats reprrd/Makefile reprrd/opendkim-reprrdimport reprrd/opendkim-reprrdimport.8 reprrd/reprrd.pc reputation/Makefile reputation/opendkim-genrates reputation/opendkim-genrates.8 reputation/opendkim-modtotals reputation/opendkim-modtotals.8 reputation/opendkim-rephistory reputation/opendkim-rephistory.8 reputation/repute.pc ]) OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/000077500000000000000000000000001337314105200201155ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/.gitignore000066400000000000000000000000431337314105200221020ustar00rootroot00000000000000Makefile Makefile.in opendkim.spec OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/Makefile.am000066400000000000000000000003151337314105200221500ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign SUBDIRS = convert docs init ldap lua patches repute spec stats systemd dist_doc_DATA = README OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/README000066400000000000000000000010231337314105200207710ustar00rootroot00000000000000This "contrib" directory of The Trusted Domain Project and its subdirectories contain files contributed by members of the community that provide functions not directly supported by the project team. The copyrights on the files in and/or below this directory are owned by the files' owners and not by The Trusted Domain Project. Support for files contained here are provided only on a best-effort basis by the project team and by the files' owners. -- Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/convert/000077500000000000000000000000001337314105200215755ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/convert/Makefile.am000066400000000000000000000002211337314105200236240ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = convert_keylist.sh OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/convert/README000066400000000000000000000006031337314105200224540ustar00rootroot00000000000000This directory contains configuration file conversion scripts that are useful when upgrading between certain major releases of OpenDKIM. They are supported by their respective authors. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. -- Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/convert/convert_keylist.sh000066400000000000000000000037621337314105200253650ustar00rootroot00000000000000#!/bin/sh # # # (c)2010 Mike Markley . Licensed under the same terms as the # OpenDKIM distribution (see ../LICENSE). force=0 while [ -n "$1" ]; do if [ "$1" = "-f" ]; then force=1 else file="$1" fi shift done if [ -z "$file" ]; then echo -n "Configuration or key list file: " read file fi if [ ! -e "$file" ]; then echo "$0: $file: file not found" >&2 exit 1 fi if grep -iq "^keylist" "$file"; then KEYLIST="$(grep -i "^keylist" "$file" | awk '{ print $2 }')" echo "Found OpenDKIM configuration file; using $KEYLIST as key list file" else # Assume we were passed a KeyList otherwise KEYLIST="$file" fi if [ -z "$KEYLIST" ]; then echo "$0: KeyList input file must be specified." >&2 exit 1 fi echo -n "Output file for KeyTable: " read KEYTABLE if [ -z "$KEYTABLE" ]; then echo "$0: KeyTable output file must be specified." >&2 exit 1 fi if [ -e "$KEYTABLE" -a $force -ne 1 ]; then echo "$0: refusing to overwrite $KEYTABLE" >&2 exit 1 fi echo -n > $KEYTABLE echo -n "Output file for SigningTable: " read SIGNINGTABLE if [ -z "$SIGNINGTABLE" ]; then echo "$0: SigningTable output file must be specified." >&2 exit 1 fi if [ -e "$SIGNINGTABLE" -a $force -ne 1 ]; then echo "$0: refusing to overwrite $SIGNINGTABLE" >&2 exit 1 fi echo -n > $SIGNINGTABLE while read line; do addresspat=$(echo $line | cut -d: -f1) domain=$(echo $line | cut -d: -f2) key=$(echo $line | cut -d: -f3) selector=$(basename $key) keyname="${selector}._domainkey.$domain" keyfile="" for f in "$key" "${key}.pem" "${key}.private"; do if [ -e "$f" ]; then keyfile="$f" fi done if [ -z "$keyfile" ]; then echo "Warning: Could not find private key file for $key (no privileges?)" >&2 keyfile="$key" fi echo "$addresspat $keyname" >> $SIGNINGTABLE echo "$keyname $domain:$selector:$keyfile" >> $KEYTABLE done < "$KEYLIST" echo "Done; please add these options to your configuration file (and remove the KeyList entry):" echo "KeyTable file:$KEYTABLE" echo "SigningTable refile:$SIGNINGTABLE" OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/docs/000077500000000000000000000000001337314105200210455ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/docs/Makefile.am000066400000000000000000000002041337314105200230750ustar00rootroot00000000000000# Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = chroot OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/docs/README000066400000000000000000000005531337314105200217300ustar00rootroot00000000000000This directory contains miscellaneous contributed documentation that may be of use to sites installing OpenDKIM. They are maintained by their respective authors. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. -- Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/docs/chroot000066400000000000000000000054021337314105200222670ustar00rootroot00000000000000OPENDKIM CHROOT NOTES ===================== Contributed by Andreas Schulze Running opendkim chroot adds an additional layer of complexity. It is disabled by default. Only advanced users only should try to enable that special configuration. To successfull setup a chroot jail you must configure opendkim to run *without* that restriction first! enabling chroot jail ==================== chroot is enabled by adding "ChangeRootDirectory /path/to/chroot" to opendkim.conf. Then you must restart opendkim. setting up syslog ================= opendkim requieres a syslog socket inside the chroot. You have to edit your syslog daemon configuration. for rsyslog: $AddUnixListenSocket /path/to/chroot/dev/log" for syslog-ng: unix-dgram("/path/to/chroot/dev/log"); After restarting the syslog daemon you may want to check if the syslog socket is really present. test -S /path/to/chroot/dev/log || echo "socket missing" setting up resolving ==================== The next point is only required if opendkim is compiled with the optional code option "USE_UNBOUND" and you activated "ResolverConfiguration" in opendkim.conf. Then you must place the unbound configuration file inside /path/to/chroot. If your unbound.conf includes other files such dnssec keys, these file must also be placed inside /path/to/chroot. opendkim.conf: ResolverConfiguration /inside_chroot/unbound.conf setup entropie ============== opendkim needs access to /dev/random or a similiar random generator. for linux: install -d /path/to/chroot/dev/ mknod --mode 666 /path/to/chroot/dev/random c 1 8 simple signing setup ==================== opendkim.conf: Mode s Domain example.org Selector default KeyFile /real/path/to/keyfile In this case no further action is required. more complex signing setup ========================== opendkim.conf: Mode s SigningTable refile:/real/path/to/signingtable KeyTable file:/real/path/to/keytable /real/path/to/signingtable: *@example.org examplekey /real/path/to/keytable: examplekey example.org:default:/inside_chroot/key.private You have to put your signing keys inside /path/to/chroot. Validation ========== validation requires additional libraries to fetch keys from dns. To copy the right libraries into the chroot you may use scripts provided by postfix. download the postfix source tarball from a mirror listed at www.postfix.org/download.html. The directory examples/chroot-setup contain scripts to setup a postfixchroot for many platforms. At least the script LINUX2 is perfect to setup a chroot for opendkim too: POSTFIX_DIR=/path/to/dkim-chroot export POSTFIX_DIR sh -x /path/to/postfix-source/examples/chroot-setup/LINUX2 Users of other platforms are invided to share their solution on the opendkim-users mailing-list. == OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/000077500000000000000000000000001337314105200210605ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/Makefile.am000066400000000000000000000002471337314105200231170ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # AUTOMAKE_OPTIONS = foreign SUBDIRS = generic redhat solaris #dist_doc_DATA = README OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/README000066400000000000000000000005401337314105200217370ustar00rootroot00000000000000The directories below here contain start/stop scripts or their equivalents for various architectures. They are supported by their respective authors. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. -- Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/generic/000077500000000000000000000000001337314105200224745ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/generic/Makefile.am000066400000000000000000000002071337314105200245270ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = opendkim OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/generic/README000066400000000000000000000016241337314105200233570ustar00rootroot00000000000000This directory contains a generic start/stop script that can be used on most UNIX systems to automate control of the opendkim filter. To install, copy it to /etc/init.d/opendkim, and ensure its mode is 0755. Then, follow the section below appropriate to your system. If you don't see your system listed, we would appreciate receiving from you instructions specific to your system once you get it working so that others who come after you can have helpful instructions. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. RHEL-based and SLES-based Linux systems: Execute "chkconfig --add opendkim" as root. This will read parameters found in the script and set up symbolic links under /etc/rc.d so that the filter is automatically started and stopped as needed. -- Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/generic/opendkim000066400000000000000000000103361337314105200242300ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # # ### BEGIN INIT INFO # Provides: opendkim # Required-Start: $syslog $time $local_fs $remote_fs $named $network # Required-Stop: $syslog $time $local_fs $remote_fs $named # Default-Start: 2 3 4 5 # Default-Stop: S 0 1 6 # Short-Description: OpenDKIM Milter # Description: The OpenDKIM milter for signing and verifying email # messages using the DomainKeys Identified Mail protocol ### END INIT INFO # # chkconfig: 345 20 80 # description: OpenDKIM milter for signing and verifying email # processname: opendkim # # This script should run successfully on any LSB-compliant system. It will # attempt to fall back to RedHatisms if LSB isn't available, or to # commonly-available utilities if it's not even RedHat. NAME=opendkim PATH=/bin:/usr/bin:/sbin:/usr/sbin DAEMON=/usr/sbin/$NAME PIDFILE=/var/run/$NAME/$NAME.pid CONFIG=/etc/$NAME.conf USER=opendkim # Implement our own status function per LSB specs. This will be used on # non-RedHat systems. od_status() { pid=$(od_getpid) if [ $? -ne 0 ]; then if [ -f $PIDFILE ]; then echo "$NAME dead but pid file exists" return 1 elif [ -d /var/lock/subsys -a -f /var/lock/subsys/$NAME ]; then echo "$NAME dead but subsys locked" return 2 else echo "$NAME is stopped" return 3 fi fi echo "$NAME (pid $pid) is running..." return 0 } od_getpid() { if [ -n "$1" -a "$1" = "-P" ]; then shift PIDFILE=$1 shift else PIDFILE=$(grep -i '^pidfile' $CONFIG | head -n 1 | awk '{print $2}') fi if [ ! -f "$PIDFILE" ]; then return 1 fi PID=$(cat "$PIDFILE") if [ -n "$(which pgrep)" ]; then for p in $(pgrep -f $DAEMON); do if [ "$PID" = "$p" ]; then echo $p return 0 fi done elif [ -x "/bin/pidof" ]; then for p in $(/bin/pidof -o %PPID $DAEMON); do if [ "$PID" = "$p" ]; then echo $p return 0 fi done fi return 1 } od_killproc() { [ -z "$1" ] && return 1 if [ -n "$2" ]; then signal=$2 else signal="TERM" fi if $(od_getpid); then pkill -"$signal" -f $1 fi } # Check for helper functions if [ -f /lib/lsb/init-functions ]; then # Use LSB functions, if available . /lib/lsb/init-functions alias od_killproc=killproc alias od_daemon=start_daemon elif [ -f /etc/init.d/functions ]; then # Use RedHat init functions if LSB isn't available . /etc/init.d/functions alias od_daemon=daemon alias log_success_msg=success alias log_warning_msg=passed alias log_failure_msg=failure alias od_killproc=killproc alias od_status=status elif [ -f /etc/rc.d/init.d/functions ]; then # Legacy RedHat init location . /etc/rc.d/init.d/functions alias od_daemon=daemon alias log_success_msg=success alias log_warning_msg=passed alias log_failure_msg=failure alias od_killproc=killproc alias od_status=status else # If all else fails, use generic commands alias od_daemon='' alias log_success_msg=echo alias log_warning_msg=echo alias log_failure_msg=echo fi if [ ! -x "$DAEMON" ]; then exit 5 fi if [ ! -f "$CONFIG" ]; then log_failure_msg "$CONFIG not found" exit 6 fi [ -r /etc/default/$NAME ] && . /etc/default/$NAME ARGS="-u $USER $ARGS" if [ -n "$SOCKET" ]; then ARGS="$ARGS -p $SOCKET" fi od_start() { echo -n "Starting OpenDKIM Milter: " od_daemon $DAEMON -x $CONFIG $ARGS if [ $? -eq 0 ]; then log_success_msg $NAME if [ -d /var/lock/subsys ]; then touch /var/lock/subsys/$NAME fi else log_failure_msg $NAME fi echo } od_stop() { echo -n "Stopping OpenDKIM Milter: " CPIDFILE="" if [ -f $CONFIG ]; then CPIDFILE=$(grep -i '^pidfile' $CONFIG | head -n 1 | awk '{print $2}') fi if [ x"$CPIDFILE" != x"" ]; then PIDFILE=$CPIDFILE fi od_killproc -p $CPIDFILE $DAEMON if [ $? -eq 0 ]; then log_success_msg $NAME if [ -d /var/lock/subsys ]; then rm -f /var/lock/subsys/$NAME fi else log_failure_msg $NAME fi echo } od_reload() { echo -n "Reloading OpenDKIM Milter configuration: " od_killproc $DAEMON USR1 if [ $? -eq 0 ]; then log_success_msg $NAME else log_failure_msg $NAME fi echo } case "$1" in start) od_start ;; stop) od_stop ;; restart|force-reload) od_stop od_start ;; reload) od_reload ;; status) od_status $NAME ;; esac OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/redhat/000077500000000000000000000000001337314105200223275ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/redhat/.gitignore000066400000000000000000000000411337314105200243120ustar00rootroot00000000000000opendkim opendkim-default-keygen OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/redhat/Makefile.am000066400000000000000000000002111337314105200243550ustar00rootroot00000000000000# Copyright (c) 2010, 2011, 2013, The Trusted Domain Project. # All rights reserved. dist_doc_DATA = opendkim opendkim-default-keygen OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/redhat/opendkim-default-keygen.in000066400000000000000000000026561337314105200274000ustar00rootroot00000000000000#!/bin/bash # Create default keys for the OpenDKIM Milter. # source function library #. /etc/rc.d/init.d/functions # Some functions to make the below more readable prog=opendkim KEYGEN=@sbindir@/$prog-genkey DKIM_SELECTOR=default DKIM_KEYDIR=@sysconfdir@/$prog/keys # Make some colors red='\033[1;31m' green='\033[1;32m' NC='\033[0m' # No Color # Pull in sysconfig settings (will override previously set functions) [ -f @sysconfdir@/sysconfig/$prog ] && . @sysconfdir@/sysconfig/$prog do_dkim_keygen() { if [ ! -s $DKIM_KEYDIR/$DKIM_SELECTOR.private ]; then echo -n $"Generating default DKIM keys: " if [ "x`hostname --domain`" = "x" ]; then echo echo -e "${red}Cannot determine host's domain name, so skipping default key generation.${NC}" else mkdir -p $DKIM_KEYDIR $KEYGEN -D $DKIM_KEYDIR -s $DKIM_SELECTOR -d `hostname --domain` chown -R root:$prog $DKIM_KEYDIR chmod 640 $DKIM_KEYDIR/$DKIM_SELECTOR.private chmod 644 $DKIM_KEYDIR/$DKIM_SELECTOR.txt echo echo -e "${green}Default DKIM keys for `hostname --domain` created in $DKIM_KEYDIR.${NC}" fi else echo -e "${red}Default DKIM keys already exist!${NC}" fi } # Create keys do_dkim_keygen OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/redhat/opendkim.in000066400000000000000000000054331337314105200244720ustar00rootroot00000000000000#!/bin/bash # # opendkim Start and stop OpenDKIM. # chkconfig: - 41 59 # description: OpenDKIM implements the DomainKeys Identified Mail (DKIM) # service and a milter-based filter application that can plug # in to any milter-aware MTA. # processname: opendkim # pidfile: /var/run/opendkim/opendkim.pid ### BEGIN INIT INFO # Provides: opendkim # Short-Description: Start and stop OpenDKIM # Description: OpenDKIM implements the DomainKeys Identified Mail # (DKIM) service and a milter-based filter application # that can plug in to any milter-aware MTA. ### END INIT INFO # OpenDKIM startup script v2.0 for RHEL/CentOS/Fedora # by Steve Jenkins (SteveJenkins.com) - 03-24-2015 # Based on a script by Andrew Colin Kissa (TopDog) for dkim-milter - 05-28-2009 # - Additional functionality to prevent multiple instances and a reload # handler by Chris LaJoie - 01-11-2011 # - Added notification (along with with current PID) if "start" is issued when # OpenDKIM is already running - 02-15-2011 # - Added support to generate default keys on start - 08-22-2011 # - Added support for /etc/sysconfig/opendkim override of default init script # setup parameters - 09-19-2011 # - Changed default stop priority - 09-19-2011 # - Updated success and warning outputs for default key generation - 09-20-2011 # - Changed default key directory ownership and permissions - 09-22-2011 # - No longer automatically creates default keys on startup (user must now manually # generate keys as privileged user after install) - 08-04-2014 # - Removed uneeded code from automatic key creation - 12-09-2014 . /etc/rc.d/init.d/functions prefix=@prefix@ exec_prefix=@exec_prefix@ RETVAL=0 prog="opendkim" DAEMON=@sbindir@/$prog CONF_FILE=@sysconfdir@/$prog.conf PID_FILE=@localstatedir@/run/$prog/$prog.pid if [ -f /etc/sysconfig/opendkim ]; then . /etc/sysconfig/opendkim fi start() { echo -n $"Starting OpenDKIM Milter: " if [ -f $PID_FILE ]; then PID=`cat $PID_FILE` echo OpenDKIM already running as pid $PID exit 2; else daemon $DAEMON -x $CONF_FILE -P $PID_FILE RETVAL=$? [ $RETVAL -eq 0 ] && touch /var/lock/subsys/opendkim echo return $RETVAL fi } stop() { echo -n $"Stopping OpenDKIM Milter: " killproc -p $PID_FILE opendkim RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/opendkim return $RETVAL } restart() { stop start } reload() { echo -n $"Reloading OpenDKIM Milter configuration: " killproc -p $PID_FILE opendkim -SIGUSR1 RETVAL=$? echo return $RETVAL } case "$1" in start) start ;; stop) stop ;; reload) reload ;; restart) restart ;; status) status -p $PID_FILE opendkim ;; condrestart) [ -f /var/lock/subsys/opendkim ] && restart || : ;; *) echo $"Usage: $0 {start|stop|status|reload|restart|condrestart}" exit 1 esac exit $? OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/solaris/000077500000000000000000000000001337314105200225345ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/solaris/Makefile.am000066400000000000000000000002241337314105200245660ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = opendkim opendkim.xml OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/solaris/opendkim000066400000000000000000000004171337314105200242670ustar00rootroot00000000000000#!/sbin/sh # # Start method script for the DKIM milter # PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin; export PATH . /lib/svc/share/smf_include.sh echo "starting opendkim" opendkim -x /etc/mail/opendkim.conf echo "started opendkim" exit $SMF_EXIT_OK #!/end OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/init/solaris/opendkim.xml000066400000000000000000000032271337314105200250700ustar00rootroot00000000000000 OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/ldap/000077500000000000000000000000001337314105200210355ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/ldap/Makefile.am000066400000000000000000000002711337314105200230710ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = example.com.ldif opendkim.ldif opendkim.schema README.LDAP OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/ldap/README.LDAP000066400000000000000000000116521337314105200224410ustar00rootroot00000000000000OPENDKIM LDAP NOTES ================== Contributed by Patrick Ben Koetter This is a brief document describing how to store and retrieve (multiple) signature keys from an LDAP server. If you are looking for detailed information that shows how to setup basic connection settings such as LDAPBindUser, LDAPBindPassword or its (additional) SASL equivalents take a look at the opendkim.conf(5) man page first. How opendkim LDAP queries work Retrieving a signature key from an LDAP server is a two step procedure: 1. Identify identity The first step attempts to find an identity that matches the From: header field. It is configured using the SigningTable parameter. opendkim will check variations of the From: header field. See the SigningTable description in opendkim.conf(5), which describes query variations and order in detail. If an identity matches the query, opendkim attempts to retrieve a selector name associated with the same LDAP object. In case opendkim was configured to apply multiple signatures the program will search for all query variations and build a list of all selector names found. 2. Retrieve signing key The second query uses the selector name to search for the associated signing key. It is configured using the KeyTable parameter. In case opendkim was configured to apply multiple signatures the program will run a query for every selector name on its list and it will try to retrieve all associated signing keys. opendkim LDAP schema and data First of all you need to populate your LDAP DIT with attributes useful for DKIM signing. Unless you plan to roll your own LDAP schema, you can use the opendkim.schema that ships with the opendkim sources. All attributes and classes in opendkim.schema use registered private enterprise numbers. You can safely import them into your LDAP namespace. There will be no collisions with other public prefixes. Note: All examples in this document refer to attributetypes and classes used in opendkim.schema. Include the schema in your LDAP server configuration to put it to use. The following examples works for openLDAPs slapd.conf: include /etc/ldap/schema/opendkim.schema Once you've included the schema and restarted the LDAP server you can start adding DKIM data to control opendkim(8) signing behaviour. The attributetype descriptions for DKIMSelector, DKIMKey, DKIMIdentity and DKIMDomain inside opendkim.schema should be selfexplanatory and tell you which attribute should carry which data. Additionally you can peek at the file example.com.ldif, which also has been shipped with opendkim sources. It contains a fully functional DIT for identities within example.com and two subdomains. Configuring LDAP queries As described in "How LDAP queries work" you need to create two queries - one to identify the selector (SigningTable) and one to retrieve the signing key (KeyTable). Depending how you configure the queries you can control if opendkim will add a single or multiple signatures and if it optionally will add the i= parameter to disclose the full signer identity in signatures. Single signature In its simpliest form the query retrieves a single signing key. It will be the key from the identity that matches opendkims query strategy best. The following example uses the opendkim.schema to configure such a query in opendkim.conf: SigningTable ldap://192.0.2.1/ou=people,dc=example,dc=com?DKIMSelector?sub?(DKIMIdentity=$d) KeyTable ldap://192.0.2.1/ou=people,dc=example,dc=com?DKIMDomain,DKIMSelector,DKIMKey,?sub?(DKIMSelector=$d) Configured that way opendkim will connect to the LDAP server on 192.0.2.1, start a subtree query at the search base "ou=people,dc=example,dc=com" and check if DKIMIdentity values match the query string. If that's the case it retrieves the value from DKIMSelector. Then, using the query defined in KeyTable, it will search for the DKIMSelector value it retrieved in the SigningTable query. If there's a match it will try to retrieve all values associated with DKIMDomain, DKIMSelector and DKIMKey. Data from these attributes at hand it will sign the message. Multiple Signatures If you want to apply all signatures whose identities match, you simply need to enable MultipleSignatures (default: no) in opendkim.conf: SigningTable ldap://192.0.2.1/ou=people,dc=example,dc=com?DKIMSelector?sub?(DKIMIdentity=$d) KeyTable ldap://192.0.2.1/ou=people,dc=example,dc=com?DKIMDomain,DKIMSelector,DKIMKey,?sub?(DKIMSelector=$d) MultipleSignatures yes Signature + User Identifier If you want to disclose a user identifier along with the signature let the SigningTable also retrieve the DKIMIdentity as second string: SigningTable ldap://192.0.2.1/ou=people,dc=example,dc=com?DKIMSelector,DKIMIdentity?sub?(DKIMIdentity=$d) KeyTable ldap://192.0.2.1/ou=people,dc=example,dc=com?DKIMDomain,DKIMSelector,DKIMKey,?sub?(DKIMSelector=$d) MultipleSignatures yes OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/ldap/example.com.ldif000066400000000000000000000176421337314105200241170ustar00rootroot00000000000000dn: dc=example,dc=com objectClass: top objectClass: dcObject objectClass: organization objectClass: DKIM dc: example o: Example Inc. DKIMSelector: example-2011 DKIMKey:: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWEFJQkFBS0JnUURWbHlK ejEwZGdjVWhWWkxHcU9VWURRRWtBQ1Q4c2ZNSjRsV1FXUTRWWE0waE9XZkRhCkEwNlFlUVFGZUZqN Dd4M3J6aWNMdHI3Yjd1cStkcUpOWldYMWhucUNENmlYOWJiTFNhWnN5ZzhqWStKU2xhUlgKek9mej N1dGhPczJ2OWF0aStBY1Y3QVV5VGtvYXNlVE9vc25jV1A3ckFaVWErQ0VwYTArUEt1aVhTUUlEQVF BQgpBb0dBWXNVSzk0cWJ4U3RkaWErUXdPalBTWDJXeEYrQ1NTNUFOOGJOaThZWmlTTjcwaytoSXcv WWF0S3JXMlExCnNKZlN2RktPbDhvZ0pGQXRXWG8rdjQrZVA3MW13L1lhcjhoeVZvQTNhWjhITW9td Dd1MmJ1VXU3NGZnY2xRSXQKbVpRQjREay9WbUh6VFVhT1IrZUN4WmQ5a1dzK0c2dThVZTlVZmhIWm Zhb1FQYUVDUVFEdllKemhpSHY3Q2pTeQpOdkF5dk5qOE9NUkxOZlNwVDc2YURNSW5FOUZCa2tROGN 0SEs3RHk1cjEzako1b0ltZGI0ZXI1bkwrYzMyWHY1CjRRWGk4SDhsQWtFQTVHd2J4bjF6bFd6amVS Z1BVSlB5RzVEejJMVzVkUEtoRGhPY0I1YzlGQ0ZVS1BsSDBYb2sKWVFlZUlST1BYNWFVTWVpbmNYW GMzYzdGRHZtcVVEYmdWUUpBRng3anlEemdqTHpObmpFRVBrSlRTdmxJckdNSAp3SnE5TkMvclNNNz NOVGdsY3hrNy9qZVhIZkE4UjBaNThENjdyc0JjUjZjdTFBd2psMTBPcm43QUtRSkFEOG54Ck9ZMGV XaXZHcFc0bVVObUpHS0t5V0Q1bmJWQUFGZXNCRS8wK09ZLzhNMERYMkFEclZ0R2grb05SbTdmYTBv QlUKWXFGVS9QZjM0d3NhM0tTT2FRSkJBT2lSNUsrL1lBelJiSm1yT0ZYRmNSL1NjSkphRG1XYTFvQ TV5dGFURkNlaQpaSTBlYVQrTkhXS2hvejZncGNFUGl0S2V6WFlUSlZUcnIxRVQ3T1lvMG1FPQotLS 0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ== dn: cn=admin,dc=example,dc=com objectClass: simpleSecurityObject objectClass: organizationalRole cn: admin description: LDAP administrator userPassword:: c2VjcmV0 dn: ou=people,dc=example,dc=com objectClass: organizationalUnit objectClass: top ou: people dn: ou=services,dc=example,dc=com objectClass: organizationalUnit objectClass: top ou: services dn: ou=bar,ou=people,dc=example,dc=com objectClass: organizationalUnit objectClass: top objectClass: DKIM DKIMKey:: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDV3dJQkFBS0JnUURDR01q Q0lLOU55Zm1tTnBTT2I0QklYa2FYSnRVSWo1WmhQQys0anBPWFNabU9ITVAxCnNxNFA4S08yRHlqd 0tQM3FXK1Z0NXhsdVFVTTVCK2ZGOENZUFhSRzliSTk3RmU5OFhqaDQzSjVZV1dWcitDT0YKc2loWV pJM0YrU3JqZnczM2R5ZzhLQ3o4L1U2QmdpRlB1M2EzU2xQSXNkMngvcnBvZDBoWUdYRHM2d0lEQVF BQgpBb0dBUVJqRzNEVFNGcWpTemVnb1VzMGFuU3JoU2ZpQUltcmw2SjZpOHFiKzRSS1NLWk9FTlhk RDRaeTNpMnZ5Ck12bk1qemxhN1UxQXZqV3RNZ2R3dUhZZWpScGIyZzcrQU16M3hXTkJQUGdiTElPQ XRSNWxtWDhMYmR4Q2hydmUKME8rVTB0Uk9kM1Z4bVZ5STBVdm9IR0JtWkFseFZ2eWdtV1hxb2g0aW dyaHRIMEVDUVFEMUV6NTFaOGZJbHVaQwpCV1pxNy9Hd0grUzRraXJqN09rbmd4RVNwYVlMa1hBMTR 3Z2V4aW5XUEJ2MCtsWGJJRFpOMVFKOWs0MHlkSEV1CnpaOEZVcUZqQWtFQXlyL0lya3FBLzlFNHFw Wjg0YTA2cHJIdVQ1dmlnaVM4V0VxTExTMFdKbEVJcWFpVDZseWkKMFBQRVpVMmtBbENWQldDZ2ZlY zIyRDc2Tlk2eS9PdGcyUUpBQkJaWEUxUXd3OHFvZW05bW50L3prdkZsT2lMTgo3bEUwTGtHRVZtQk czYWlHUzQvR3dlU2lLLzJDcGRwSzlrV2FRa0FNTTVYelkrVUhRaldSc21BSGF3SkFZbS9vCjlFNHl BWUpJTy9LaW9VTms1WWdnQjBETklaaktaU2VVR1JQNTNCS2QzUmwrNzF1WXBWQ2xPdllPT2gxN3JN ZTAKUkV5ZEFUTGFjbVJkSEpUL1NRSkFjNEVxSWpmUUZuNE9FbmFRakR5YlBnY1MrMXNqM3UxSkhkb HR2WTkzTE5yeQp3bmx6dDN4dndUWDI5QllDMG5IdHBIQlYydzFESzhYVVhDMGQrVWZ5M0E9PQotLS 0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ== DKIMSelector: bar-2011 DKIMDomain: bar.example.com DKIMIdentity: @bar.example.com ou: bar dn: uid=opendkim,ou=services,dc=example,dc=com uid: opendkim userPassword:: c2VjcmV0 objectClass: account objectClass: top objectClass: simpleSecurityObject dn: uniqueIdentifier=alice@bar.example.com,ou=bar,ou=people,dc=example,dc=com DKIMSelector: alice-2011 userPassword:: c2VjcmV0 objectClass: organizationalPerson objectClass: person objectClass: top objectClass: PostfixBookMailAccount objectClass: extensibleObject objectClass: DKIM cn: Alice sn: Alice givenName: Lastname DKIMKey:: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWGdJQkFBS0JnUURyYW9Y UWNuSmNjaWFIMWhqMjYyWFZ0SVl1NU13Q1QwdXdXYzFpL3RxMVNQT25pRXB2ClV4Y3pTM3d0ckw3U DJXd3FTeVd6V3g3cGN4Q3NqNXVuQjV1OXMxT2h1M1FScmZ5WGQ1VHh6ejlaYlVkVjhDMVYKOG0rQ3 RVU3UweUtjZUJuOGJIYzJCMzA5VUpZblpueDZacTZYZTNQRTBFOXJ6cGVIdGJIYTRwajV1UUlEQVF BQgpBb0dCQUs3ZUZJSU8wU1ljWU1TYjR6VmZDK2pmVEtEK3NRK3lLUzNZdHZpbkNIeUtzUHFzQVdh S0dQeXdRSkNJCjliL2M2RHpPVHpYWUpMRVNHTHVsZk9Cb2hXVEtXdjBlZS9HVzRtS1M3Vkg5ZjdtL 3VHQktTc3FQenpLOVlZaVUKNWxlT0NvT0xaUnZldmYwLzhZV2tzNFZ0b1ZleVhpSi9BZHJCdjlkem gxSzZGVWJSQWtFQTk5bHJoaEc0eFVyYgpvbE43T2ZBVWVFWXQydUpRbnZWMDYrbVZwMGdqanY5VXN jSWxjR1lrMjMvSnBmSW1XRU5HTGEwUDJrWUJPT1VyCitnM1BZTWRQN1FKQkFQTW9ia3BVVDdaYzkw YXBJbGc4ZnBHOWUyTnRRQ2hVaDZ1VVd3TjJKNHVwVmt4bTd6MTYKSGd3NWJhWG5idkxhcTF4cTJTS 1dQRmpNS3NjTnJQVldYMzBDUVFDQ0FBbVU5ZUNyb3pzV3BxRUEzN3RzNXFxUQpuNXBYOWpsUXNHRn RyN251L0dBcEtNTklkRnNxd3BrN01Jc0tTcWNadUNlVGZwcVBoQzBQNklSNHA3SjFBa0VBCjBsb2N wMUt1cnMxWDRabjVxeW1TT1JRWmhSY0RGS0NqeVl3Sy9FQ2Z6MU5MNDhaOG1zdGs2U0JaT2RldmhJ b2wKQ2tzbzBxSHpUTUk3RTM1Q0xPOXVwUUpBUFZBWGNrYTAvMSsvRVlIWi90bTVNVnlTOHZ6Yko5d HlmSk0wdVdXSApNV3c1UC8xL3VQR1pseWxycjlKWkJPckJqYTl5OHQyVm11b1YvTVlBTU5EOXlnPT 0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0= mail: alice@bar.example.com DKIMDomain: bar.example.com DKIMIdentity: alice@bar.example.com uniqueIdentifier: alice@bar.example.com dn: ou=foo,ou=people,dc=example,dc=com objectClass: organizationalUnit objectClass: top objectClass: DKIM DKIMKey:: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWFFJQkFBS0JnUUMvdjh6 Njc4RlgvM2NBTkIvYjBoZTJ6VDNZMmpYTDhMcnJvQmZ0TjZleWdqSmg5TlNnCk5MSWIvRFBzeFlWV 0praE5IbGpEa2FIMFREd0tHZXdqcXhvSzJ1VG5HOXlrcS9rWTJER2NhaWNRVXRISkVGQkYKVlZHVH JpamhNZDg2bll3YWFGNjBwaFV4bDVuUGNhdkRtVGg1RFBMTllZYUxrSlJpMUpJZWkxcTdwd0lEQVF BQgpBb0dBT1pHQUhTYTJTWkV0VFNaWkdrb3RUSGk2Uk16ZXNlZ0lkbzJPSVc1QUx0dmYvSURoQldo TXdSSXJGTDhJCmxTRFJQRFlNT0VzVThKK2l0dldwYTl3RzZRNWFaNCtYMXh2T3RvNmQ1dWltWVNSY zhEd3U0cjFVS05HQi9aMmoKZWVHS3JjZnlyUFhTdUlqMjJ3TnZBSjQ2RGxLdEIyMGFpcWw3YUhqRU s1ZlpQR0VDUVFEZ2laQTVMcnRWSFFxTQpIUERjL2tYNU9jRHFxZ3pockxpaUx4eWtQeWRtZWVXQ21 3b200Ung5bTRCVnkzY3dCM2RKSFJPUVVUMmFZbnAvCjNheGNJcUZiQWtFQTJwNFY5alFMSHE1dmNj RUVXeE85NEVFY3NJTUFXTE14RFdWMDAva3QyUkx4clBxM1BhOXkKS0tBY2ZrTnduZTJuN2RlU2NlU kd4NG1USWxHY2pCcjBwUUpCQUlzd2Uza1hJUVdvRlF1NlBRMmhpbHJ1bEVwagowOHhwdDZMQ05hMF RnU2NqVlVUYk96WFN3a2lUQnNFb2VlQUtJTVh3QWxxcUlkZjhTQmZQb0xNVXZKVUNRQ3Q2CmlVK2Y 1aDVCL3ZRV3VURUw2aFZ4bmEwVlFMcGpXUHdiRTNNYytadFVnekF0NU1lbDN3UnBZNEZSRkZLMGMx T0EKTGlYc2lvOGdzMXg5OHE2Q3Bla0NRUURDNEp0M1JZenZONmdvTk5uZUdHZzVmQnBvSFNMWmpna TJoaG0xMWFIMwpqTnVQTTNyR3VDMUdPMGpZMVRjRURoNDdQOFlZcUdiamgyTmVIMmVVTmduZgotLS 0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQ== DKIMSelector: foo-2011 DKIMDomain: foo.example.com DKIMIdentity: @foo.example.com ou: foo dn: uniqueIdentifier=bob@foo.example.com,ou=foo,ou=people,dc=example,dc=com givenName: Lastname userPassword:: c2VjcmV0 DKIMKey:: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWGdJQkFBS0JnUURyYW9Y UWNuSmNjaWFIMWhqMjYyWFZ0SVl1NU13Q1QwdXdXYzFpL3RxMVNQT25pRXB2ClV4Y3pTM3d0ckw3U DJXd3FTeVd6V3g3cGN4Q3NqNXVuQjV1OXMxT2h1M1FScmZ5WGQ1VHh6ejlaYlVkVjhDMVYKOG0rQ3 RVU3UweUtjZUJuOGJIYzJCMzA5VUpZblpueDZacTZYZTNQRTBFOXJ6cGVIdGJIYTRwajV1UUlEQVF BQgpBb0dCQUs3ZUZJSU8wU1ljWU1TYjR6VmZDK2pmVEtEK3NRK3lLUzNZdHZpbkNIeUtzUHFzQVdh S0dQeXdRSkNJCjliL2M2RHpPVHpYWUpMRVNHTHVsZk9Cb2hXVEtXdjBlZS9HVzRtS1M3Vkg5ZjdtL 3VHQktTc3FQenpLOVlZaVUKNWxlT0NvT0xaUnZldmYwLzhZV2tzNFZ0b1ZleVhpSi9BZHJCdjlkem gxSzZGVWJSQWtFQTk5bHJoaEc0eFVyYgpvbE43T2ZBVWVFWXQydUpRbnZWMDYrbVZwMGdqanY5VXN jSWxjR1lrMjMvSnBmSW1XRU5HTGEwUDJrWUJPT1VyCitnM1BZTWRQN1FKQkFQTW9ia3BVVDdaYzkw YXBJbGc4ZnBHOWUyTnRRQ2hVaDZ1VVd3TjJKNHVwVmt4bTd6MTYKSGd3NWJhWG5idkxhcTF4cTJTS 1dQRmpNS3NjTnJQVldYMzBDUVFDQ0FBbVU5ZUNyb3pzV3BxRUEzN3RzNXFxUQpuNXBYOWpsUXNHRn RyN251L0dBcEtNTklkRnNxd3BrN01Jc0tTcWNadUNlVGZwcVBoQzBQNklSNHA3SjFBa0VBCjBsb2N wMUt1cnMxWDRabjVxeW1TT1JRWmhSY0RGS0NqeVl3Sy9FQ2Z6MU5MNDhaOG1zdGs2U0JaT2RldmhJ b2wKQ2tzbzBxSHpUTUk3RTM1Q0xPOXVwUUpBUFZBWGNrYTAvMSsvRVlIWi90bTVNVnlTOHZ6Yko5d HlmSk0wdVdXSApNV3c1UC8xL3VQR1pseWxycjlKWkJPckJqYTl5OHQyVm11b1YvTVlBTU5EOXlnPT 0KLS0tLS1FTkQgUlNBIFBSSVZBVEUgS0VZLS0tLS0= objectClass: organizationalPerson objectClass: person objectClass: top objectClass: PostfixBookMailAccount objectClass: extensibleObject objectClass: DKIM cn: Alice uniqueIdentifier: bob@foo.example.com DKIMIdentity: bob@foo.example.com DKIMDomain: foo.example.com mail: bob@foo.example.com DKIMSelector: bob-2011 sn: Bob OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/ldap/opendkim.ldif000066400000000000000000000017741337314105200235140ustar00rootroot00000000000000dn: cn=opendkim,cn=schema,cn=config objectClass: olcSchemaConfig cn: opendkim olcAttributeTypes: {0}( 1.3.6.1.4.1.29426.2.2.1.1 NAME 'DKIMSelector' DESC 'Se lector name associated with DKIM signing key' EQUALITY caseExactIA5Match SYNT AX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: {1}( 1.3.6.1.4.1.29426.2.2.1.2 NAME 'DKIMKey' DESC 'DKIM si gning key' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SI NGLE-VALUE ) olcAttributeTypes: {2}( 1.3.6.1.4.1.29426.2.2.1.3 NAME 'DKIMIdentity' DESC 'Th e Agent or User Identifier (AUID)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1. 4.1.1466.115.121.1.26 SINGLE-VALUE ) olcAttributeTypes: {3}( 1.3.6.1.4.1.29426.2.2.1.4 NAME 'DKIMDomain' DESC 'DKIM sender domain' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1. 26 SINGLE-VALUE ) olcObjectClasses: {0}( 1.3.6.1.4.1.29426.2.2.2.1 NAME 'DKIM' DESC 'DKIM Select or and Key container' SUP top AUXILIARY MUST ( DKIMSelector $ DKIMKey ) MAY ( DKIMIdentity $ DKIMDomain ) ) OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/ldap/opendkim.schema000066400000000000000000000022031337314105200240220ustar00rootroot00000000000000# # state of mind () # Patrick Ben Koetter, p@state-of-mind.de # # Private Enterprise Number: 29426 # # OID prefix: 1.3.6.1.4.1.29426 # openDKIM: 1.3.6.1.4.1.29426.2.2 # attributes: 1.3.6.1.4.1.29426.2.2.1 # classes: 1.3.6.1.4.1.29426.2.2.2 # attributetype ( 1.3.6.1.4.1.29426.2.2.1.1 NAME 'DKIMSelector' DESC 'Selector name associated with DKIM signing key' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.29426.2.2.1.2 NAME 'DKIMKey' DESC 'DKIM signing key' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.29426.2.2.1.3 NAME 'DKIMIdentity' DESC 'The Agent or User Identifier (AUID)' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) attributetype ( 1.3.6.1.4.1.29426.2.2.1.4 NAME 'DKIMDomain' DESC 'DKIM sender domain' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) objectclass ( 1.3.6.1.4.1.29426.2.2.2.1 NAME 'DKIM' AUXILIARY DESC 'DKIM Selector and Key container' SUP top MAY ( DKIMIdentity $ DKIMDomain ) MUST ( DKIMSelector $ DKIMKey )) OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/lua/000077500000000000000000000000001337314105200206765ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/lua/Makefile.am000066400000000000000000000002371337314105200227340ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = authheaders-check-setup-hook.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/lua/README000066400000000000000000000005061337314105200215570ustar00rootroot00000000000000This directory contains sample Lua scripts for use with the opendkim filter. They are supported by their respective authors. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. -- Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/lua/authheaders-check-setup-hook.lua000066400000000000000000000047121337314105200270510ustar00rootroot00000000000000-- Copyright (c) 2010 Jozsef Kovacs and Alex Beregszaszi -- -- Development kindly sponsored by Datira (www.datira.com), -- a professional hosting company. -- -- License: MIT -- local logging_enabled = 1 local function logger (logwhat) if logging_enabled == 1 then odkim.log(ctx, "LUA-SETUP "..logwhat) end end local function signer (domain) if odkim.sign(ctx, domain) == 1 then logger("Signing requested") else logger("Signing failed") end end -- Get SASL username local author = odkim.get_mtasymbol(ctx, "{auth_authen}") -- Incoming mail (without sasl username), verify only if author == nil then odkim.verify(ctx) return nil end logger("SASL username: "..author) -- Sign mail using the key associated to the envelope sender domain local mailfromdomain = odkim.get_fromdomain(ctx) local mailfrom = odkim.get_mtasymbol(ctx, "{mail_addr}") local headerfromaddr = odkim.get_header(ctx, "From", 0) logger("Mail from domain: "..mailfromdomain) logger("Mail from address: "..mailfrom) logger("Header from address: "..headerfromaddr) -- TODO: regexp email matching for headerfromaddr if string.find(headerfromaddr, mailfrom) ~= nil then -- If we have a direct match, sign the mail if author == mailfrom then signer(mailfromdomain) return nil end -- Check for additional possible sender aliases -- requires luasql-mysql require "luasql.mysql" local sql = luasql.mysql() if sql ~= nil then local conn = sql:connect("dbname", "dbuser", "dbpass", "db.example.com") if conn ~= nil then local cur = conn:execute(string.format("select * from alias where address=\"%s\" and goto like \"%%%s%%\"", mailfrom, author)) if cur ~= nil then if cur:numrows() > 0 then cur:close() conn:close() sql:close() logger("Alias found in SQL") signer(mailfromdomain) return nil end logger("No alias in SQL") cur:close() end conn:close() odkim.set_result(ctx, SMFIS_REJECT) return nil end sql:close() -- temporary failure: hope to process it again and SQL is available the second time odkim.set_result(ctx, SMFIS_TEMPFAIL) return nil end end -- If we got this far we have a forged sender associated to the sasl username odkim.set_result(ctx, SMFIS_REJECT) return nil OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/patches/000077500000000000000000000000001337314105200215445ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/patches/Makefile.am000066400000000000000000000002421337314105200235760ustar00rootroot00000000000000# Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = opendkim-spam-ignore-cmdswitch.patch OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/patches/README000066400000000000000000000010271337314105200224240ustar00rootroot00000000000000This directory contains miscellaneous contributed patches that may be of use to sites installing OpenDKIM. They are maintained by their respective authors. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. The patches are: opendkim-spam-ignore-cmdswitch.patch Andreas Schulze Adds an ignored "-N" switch to opendkim-spam to allow compatibility with some versions of amavisd-new. -- Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/patches/opendkim-spam-ignore-cmdswitch.patch000066400000000000000000000014711337314105200306000ustar00rootroot00000000000000Index: dv-opendkim-2.5.0.beta8/opendkim/opendkim-spam.c =================================================================== --- dv-opendkim-2.5.0.beta8.orig/opendkim/opendkim-spam.c 2011-12-15 21:54:21.000000000 +0100 +++ dv-opendkim-2.5.0.beta8/opendkim/opendkim-spam.c 2011-12-18 12:16:37.000000000 +0100 @@ -32,7 +32,7 @@ /* definitions, macros, etc. */ #define BUFRSZ 1024 -#define CMDLINEOPTS "b:c:d:fh:o:p:P:s:u:vV" +#define CMDLINEOPTS "b:c:d:fh:N:o:p:P:s:u:vV" #define DEFDBBACKEND SQL_BACKEND #define DEFCONFFILE CONFIG_BASE "/opendkim-spam.conf" #define DEFDBHOST "localhost" @@ -174,6 +174,12 @@ dbhost = optarg; break; + case 'N': + /* accept and ignore any -N switch + * added by the quarantine feature of amavisd-new + */ + break; + case 'P': dbport = optarg; break; OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/repute/000077500000000000000000000000001337314105200214215ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/repute/Makefile.am000066400000000000000000000001431337314105200234530ustar00rootroot00000000000000# Copyright (c) 2014, The Trusted Domain Project. All rights reserved. dist_doc_DATA = repute.py OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/repute/repute.py000066400000000000000000000135771337314105200233140ustar00rootroot00000000000000#!/usr/bin/env python # # sudo yum-builddep MySQL-python / sudo apt-get build-dep python-mysqldb # Prereq: # pip install begins saratoga twisted.enterprise.adbapi MySQL-python # # usage ./repute.py --help # # URLs are versioned: # # wget -S --header 'Accept: application/reputon+json' http://localhost:8000/v1/reporter/dan -O - import begin from saratoga.api import SaratogaAPI from saratoga.outputFormats import OutputRegistry from twisted.enterprise import adbapi from twisted.internet import defer import itertools import json class DKIM(object): class v1(object): @defer.inlineCallbacks def report_GET(self, request, params, reporter, subject): # hint to aid overabuse of service request.setHeader('Cache-control', 'max-age=1') query1 = '''SELECT ratio_high, UNIX_TIMESTAMP(updated), rate_samples FROM predictions WHERE name = %(subject)s AND reporter = 0''' query2 = '''SELECT daily_limit_low FROM predictions JOIN reporters ON reporters.id=predictions.reporter WHERE predictions.name = %(subject)s AND reporters.name = %(reporter)s ''' res1, res2 = yield defer.DeferredList([ self.cp.runQuery(query1, {'subject': subject }), self.cp.runQuery(query2, {'subject': subject, 'reporter': reporter }) ]) reputons = { "assertion": "spam", "rated": subject, "identity": "dkim", } if res1[0] and res1[1]: res1 = res1[1][0] reputons["rating"] = res1[0] reputons["sample-size"] = res1[2] reputons["generated"] = res1[1] if res2[0] and res2[1]: res2 = res2[1][0] reputons['rate'] = res2[0] defer.returnValue( { "application": "email-id", "reputons": [ reputons ] }) @defer.inlineCallbacks def domain_reporter_GET(self, request, params, domain, reporter): request.setHeader('Cache-control', 'max-age=1') fields = [ 'name', 'updated', 'rate_samples', 'rate_max', 'rate_avg', 'rate_stddev', 'rate_high', 'ratio_max', 'ratio_avg', 'ratio_stddev', 'ratio_high', 'daily_limit_high', 'daily_limit_low', 'today_mail', 'today_spam' ] query = 'SELECT ' + ','.join('predictions.' + f for f in fields) + ''' FROM domains JOIN predictions ON domains.id=predictions.domain JOIN reporters ON reporters.id=predictions.reporter WHERE domains.name = %(domain)s AND reporters.name = %(reporter)s ''' rows = yield self.cp.runQuery(query, {'domain': domain, 'reporter': reporter}) if rows: ret = dict(itertools.izip(fields, rows[0])) else: ret = 0 defer.returnValue(ret) @defer.inlineCallbacks def reporter_GET(self, request, params, reporter): request.setHeader('Cache-control', 'max-age=1') fields = [ 'reporter', 'name', 'updated', 'rate_samples', 'rate_max', 'rate_avg', 'rate_stddev', 'rate_high', 'ratio_max', 'ratio_avg', 'ratio_stddev', 'ratio_high', 'daily_limit_high', 'daily_limit_low', 'today_mail', 'today_spam' ] query = 'SELECT domains.name,' + ','.join('predictions.' + f for f in fields) + ''' FROM predictions JOIN reporters ON reporters.id=predictions.reporter LEFT JOIN domains ON predictions.domain = domains.id WHERE reporters.name = %(reporter)s ''' fields = ['domain'] + fields rows = yield self.cp.runQuery(query, { 'reporter' : reporter } ) if rows: ret = dict(itertools.izip(fields, rows[0])) request.setHeader('Last-modified', rows[0][3].strftime("%A, %d, %B %Y %H:%M GMT")) else: ret = False defer.returnValue(ret) DKIM_APIDef = { "metadata": {"versions": [1]}, "endpoints": [ { "endpoint": 'report/([^/]*)/(.*)', "func": 'report', "getProcessors": [{"versions": [1]}] }, { "endpoint": 'domain/([^/]*)/([^/]*)', "func": 'domain_reporter', "getProcessors": [{"versions": [1]}] }, { "endpoint": 'reporter/([^/]*)', "func": 'reporter', "getProcessors": [{"versions": [1]}] }, ] } class Database: def __init__(self,user,password,host,database): self.cp = adbapi.ConnectionPool('MySQLdb',user=user, passwd=password, host=host, db=database) def jsonDateFormatter(status, data): def _todate(obj): return obj.strftime('%Y%m%d %H%M%S') resp = { "status": status, "data": data } return json.dumps(resp, default=_todate) @begin.start def run(host="localhost", user="opendkim", password="opendkim", database="opendkim", bindAddress='', bindPort=8000): "This program runs a web server to retrieve reputation data from the opendkim database" outputRegistry = OutputRegistry('application/reputon+json') outputRegistry.register('application/reputon+json', jsonDateFormatter) outputRegistry.register('text/html', jsonDateFormatter) api = SaratogaAPI(DKIM, DKIM_APIDef, serviceClass=Database(user=user, password=password, host=host, database=database), outputRegistry=outputRegistry) api.run(port=bindPort) OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/spec/000077500000000000000000000000001337314105200210475ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/spec/Makefile.am000066400000000000000000000002521337314105200231020ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # AUTOMAKE_OPTIONS = foreign dist_doc_DATA = opendkim.spec.in EXTRA_DIST = opendkim.spec OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/spec/README000066400000000000000000000005501337314105200217270ustar00rootroot00000000000000This directory contains a prototype spec file for use in converting this source tarball into an RPM for installation on Linux systems that use the RPM system. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. -- Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/spec/opendkim.spec.in000066400000000000000000000105551337314105200241440ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # Summary: An open source library and milter for providing DKIM service Name: opendkim Version: @VERSION@ Release: 1 License: BSD Group: System Environment/Daemons Requires: libopendkim = %{version}-%{release} BuildRequires: sendmail-devel, openssl-devel @SPECREQUIRES@ @SPECBUILDREQUIRES@ Source: opendkim-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-root Prefix: %{_prefix} %description The Trusted Domain Project is a community effort to develop and maintain a C library for producing DKIM-aware applications and an open source milter for providing DKIM service through milter-enabled MTAs. %package -n libopendkim Summary: An open source DKIM library Group: System Environment/Libraries %description -n libopendkim This package contains the library files required for running services built using libopendkim. %package -n libopendkim-devel Summary: Development files for libopendkim Group: Development/Libraries Requires: libopendkim %description -n libopendkim-devel This package contains the static libraries, headers, and other support files required for developing applications against libopendkim. %prep %setup %build # Required for proper OpenSSL support on some versions of RedHat if [ -d /usr/include/kerberos ]; then INCLUDES="$INCLUDES -I/usr/include/kerberos" fi ./configure --prefix=%{_prefix} --sysconfdir=%{_sysconfdir} --libdir=%{_libdir} --mandir=%{_mandir} @SPECCONFIGURE@ CPPFLAGS="$INCLUDES" make %install make install DESTDIR="$RPM_BUILD_ROOT" mkdir -p "$RPM_BUILD_ROOT"%{_sysconfdir} mkdir -p "$RPM_BUILD_ROOT"%{_initrddir} install -m 0755 contrib/init/generic/opendkim "$RPM_BUILD_ROOT"%{_initrddir}/%{name} echo '## Basic OpenDKIM config file for verification only ## See opendkim.conf(5) or %{_docdir}/%{name}-%{version}/opendkim.conf.sample for more PidFile %{_localstatedir}/run/opendkim/opendkim.pid Mode v Syslog yes #Umask 002 #UserID opendkim:mail #Socket local:%{_localstatedir}/run/opendkim/opendkim.socket Socket inet:8891@localhost ## After setting Mode to "sv", running ## opendkim-genkey -D %{_sysconfdir}/opendkim -s key -d `hostname --domain` ## and putting %{_sysconfdir}/opendkim #Canonicalization relaxed/simple #Domain example.com # change to domain #Selector key #KeyFile %{_sysconfdir}/opendkim/key.private ' > "$RPM_BUILD_ROOT"%{_sysconfdir}/opendkim.conf rm -r "$RPM_BUILD_ROOT"%{_prefix}/share/doc/opendkim %post if ! getent passwd opendkim >/dev/null 2>&1; then %{_sbindir}/useradd -M -d %{_localstatedir}/lib -r -s /bin/false opendkim if ! getent group opendkim >/dev/null; then %{_sbindir}/groupadd opendkim %{_sbindir}/usermod -g opendkim opendkim fi if getent group mail >/dev/null; then %{_sbindir}/usermod -G mail opendkim fi fi test -d %{_localstatedir}/run/opendkim || mkdir %{_localstatedir}/run/opendkim chown opendkim:opendkim %{_localstatedir}/run/opendkim if [ ! -d %{_sysconfdir}/opendkim ]; then mkdir %{_sysconfdir}/opendkim chmod o-rx %{_sysconfdir}/opendkim opendkim-genkey -D %{_sysconfdir}/opendkim -s key -d `hostname --domain` chown -R opendkim:opendkim %{_sysconfdir}/opendkim fi if [ -x /sbin/chkconfig ]; then /sbin/chkconfig --add opendkim elif [ -x /usr/lib/lsb/install_initd ]; then /usr/lib/lsb/install_initd opendkim fi %preun if [ $1 = 0 ]; then service opendkim stop && rm -f %{_localstatedir}/run/opendkim/opendkim.sock && rmdir %{_localstatedir}/run/opendkim 2>/dev/null if [ -x /sbin/chkconfig ]; then /sbin/chkconfig --del opendkim elif [ -x /usr/lib/lsb/remove_initd ]; then /usr/lib/lsb/remove_initd opendkim fi userdel opendkim if getent group opendkim >/dev/null; then groupdel opendkim fi fi %clean if [ "$RPM_BUILD_ROOT" != "/" ]; then rm -r "$RPM_BUILD_ROOT" fi %files %defattr(-,root,root) %doc FEATURES KNOWNBUGS LICENSE LICENSE.Sendmail README RELEASE_NOTES RELEASE_NOTES.Sendmail %doc contrib/convert/convert_keylist.sh opendkim/*.sample %doc opendkim/opendkim.conf.simple-verify opendkim/opendkim.conf.simple %config(noreplace) %{_sysconfdir}/opendkim.conf %config %{_initrddir}/%{name} %{_mandir}/*/* %{_sbindir}/* @SPECBINDIR@ %files -n libopendkim %defattr(-,root,root) %{_libdir}/*.so.* %files -n libopendkim-devel %defattr(-,root,root) %doc libopendkim/docs/*.html %{_includedir}/* %{_libdir}/*.a %{_libdir}/*.la %{_libdir}/*.so %{_libdir}/pkgconfig/*.pc OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/stats/000077500000000000000000000000001337314105200212535ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/stats/Makefile.am000066400000000000000000000002421337314105200233050ustar00rootroot00000000000000# Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = opendkim-fixipaddrs.pl \ stats.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/stats/README000066400000000000000000000005461337314105200221400ustar00rootroot00000000000000This directory contains two files: stats.lua -- sample Lua script for processing local enhancements to the statistics reporting system (see the "stats" directory of the main package) opendkim-fixipaddrs.pl -- perl script for removing duplicate entries from the ipaddr table; if you were doing stats back when such a bug existed, you might find this useful OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/stats/opendkim-fixipaddrs.pl000077500000000000000000000124771337314105200255670ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2011, The Trusted Domain Project. All rights reserved. # # Script to clean out duplicate entries in the "ipaddrs" table, and update # the "messages" table accordingly. ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::mysql; # general my $progname = basename($0); my $version = "\@VERSION@"; my $verbose = 0; my $helponly = 0; my $maxid; my $dup; my $idx; my $addr; my $nrows; my $dbi_s; my $dbi_s_getaddr; my $dbi_s_getdup; my $dbi_s_repair; my $dbi_s_cleanup; my $dbi_h; my $dbi_a; my $thresh; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "mysql"; ### ### NO user-serviceable parts beyond this point ### sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host DB host [$def_dbhost]\n"; print STDERR "\t--dbname=name DB name [$def_dbname]\n"; print STDERR "\t--dbpasswd=pwd DB password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port DB port [$def_dbport]\n"; print STDERR "\t--dbuser=user DB user [$def_dbuser]\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--verbose verbose output\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'help!' => \$helponly, 'verbose!' => \$verbose, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } # apply defaults if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # get the highest ID $dbi_s = $dbi_h->prepare("SELECT MAX(id) FROM ipaddrs"); if (!$dbi_s->execute) { print STDERR "$progname: can't get maximum ID\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } else { $dbi_a = $dbi_s->fetchrow_arrayref(); if (defined($dbi_a->[0])) { $maxid = $dbi_a->[0]; } else { print STDERR "$progname: can't get maximum ID\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } } if ($verbose) { print STDERR "$progname: maximum ID is $maxid\n"; } $dbi_s->finish; $dbi_s_getaddr = $dbi_h->prepare("SELECT addr FROM ipaddrs WHERE id = ?"); $dbi_s_getdup = $dbi_h->prepare("SELECT id FROM ipaddrs WHERE addr = ? AND id > ?"); $dbi_s_repair = $dbi_h->prepare("UPDATE messages SET ip = ? WHERE ip = ?"); $dbi_s_cleanup = $dbi_h->prepare("DELETE FROM ipaddrs WHERE id = ?"); for ($idx = 1; $idx < $maxid; $idx++) { $dbi_s_getaddr->execute($idx); $dbi_a = $dbi_s_getaddr->fetchrow_arrayref(); if (defined($dbi_a->[0])) { $addr = $dbi_a->[0]; } else { print STDERR "$progname: skipping id $idx\n"; $dbi_s_getaddr->finish; next; } $dbi_s_getaddr->finish; $dbi_s_getdup->execute($addr, $idx); $dbi_a = $dbi_s_getdup->fetchrow_arrayref(); if (defined($dbi_a->[0])) { $dup = $dbi_a->[0]; if ($verbose) { print STDERR "$progname: id $idx duplicate $dup found\n"; } } else { $dbi_s_getdup->finish; next; } $dbi_s_getdup->finish; $nrows = $dbi_s_repair->execute($idx, $dup); if ($nrows == -1) { print STDERR "$progname: error updating messages table for id $idx\n"; $dbi_s_repair->finish; next; } elsif ($verbose) { print STDERR "$progname: $nrows row(s) updated\n"; } $dbi_s_repair->finish; if ($dbi_s_cleanup->execute($dup) == -1) { print STDERR "$progname: error cleaning ipaddrs table for id $dup\n"; $dbi_s_cleanup->finish; next; } elsif ($verbose) { print STDERR "$progname: id $dup removed from ipaddrs\n"; } $dbi_s_cleanup->finish; } # all done! if ($verbose) { print STDERR "$progname: done\n"; } $dbi_h->disconnect; exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/stats/stats.lua000066400000000000000000000034161337314105200231200ustar00rootroot00000000000000-- stats.lua -- conventional stats extensions -- -- Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. -- -- Referencing this as StatisticsScript from an opendkim that has both "stats" -- and "lua" enabled will produce some extended stats lines for each message -- that indicate whether the message passed SPF and/or SenderID, and -- whether or not SpamAssassin thought the message was spam. This might -- be useful for data correlation at the data aggregation point. -- -- SpamAssassin -- spam = odkim.get_header(ctx, "X-Spam-Status", 0) if spam == nil then odkim.stats(ctx, "spam", "-1") elseif string.sub(spam, 1, 3) == "No," or string.sub(spam, 2, 4) == "No," then odkim.stats(ctx, "spam", "0") elseif string.sub(spam, 1, 4) == "Yes," or string.sub(spam, 2, 5) == "Yes," then odkim.stats(ctx, "spam", "1") else odkim.stats(ctx, "spam", "-1") end -- -- SPF/Sender-ID -- n = 0 done = 0 found = 0 while (done == 0) do ares = odkim.get_header(ctx, "Authentication-Results", n) if ares == nil then done = 1 else spf = string.find(ares, "spf=", 1, true) if spf ~= nil then done = 1 found = 1 if string.find(ares, "spf=pass", 1, true) ~= nil then odkim.stats(ctx, "spf", "1") elseif string.find(ares, "spf=fail", 1, true) ~= nil then odkim.stats(ctx, "spf", "0") else odkim.stats(ctx, "spf", "-1") end if string.find(ares, "sender-id=pass", 1, true) ~= nil then odkim.stats(ctx, "senderid", "1") elseif string.find(ares, "sender-id=fail", 1, true) ~= nil then odkim.stats(ctx, "senderid", "0") else odkim.stats(ctx, "senderid", "-1") end end end n = n + 1 end if found == 0 then odkim.stats(ctx, "spf", "-1") odkim.stats(ctx, "senderid", "-1") end odkim.stats(ctx, "rcpts", tostring(odkim.rcpt_count(ctx))) OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/systemd/000077500000000000000000000000001337314105200216055ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/systemd/.gitignore000066400000000000000000000000211337314105200235660ustar00rootroot00000000000000opendkim.service OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/systemd/Makefile.am000066400000000000000000000001521337314105200236370ustar00rootroot00000000000000# Copyright (c) 2013, The Trusted Domain Project. All rights reserved. dist_doc_DATA = opendkim.service OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/systemd/README000066400000000000000000000005321337314105200224650ustar00rootroot00000000000000This directory includes files meant to be incorporated into Linux distributions for use with systemd. They are supported by their respective authors. Please submit bug reports and feature requests to opendkim-users@lists.opendkim.org or via the trackers on SourceForge. -- Copyright (c) 2013, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/contrib/systemd/opendkim.service.in000066400000000000000000000015311337314105200254020ustar00rootroot00000000000000# If you are using OpenDKIM with SQL datasets it might be necessary to start OpenDKIM after the database servers. # For example, if using both MariaDB and PostgreSQL, change "After=" in the "[Unit]" section to: # After=network.target nss-lookup.target syslog.target mariadb.service postgresql.service [Unit] Description=DomainKeys Identified Mail (DKIM) Milter Documentation=man:opendkim(8) man:opendkim.conf(5) man:opendkim-genkey(8) man:opendkim-genzone(8) man:opendkim-testadsp(8) man:opendkim-testkey http://www.opendkim.org/docs.html After=network.target nss-lookup.target syslog.target [Service] Type=forking PIDFile=@localstatedir@/run/opendkim/opendkim.pid EnvironmentFile=-@sysconfdir@/sysconfig/opendkim ExecStart=@sbindir@/opendkim $OPTIONS ExecReload=/bin/kill -USR1 $MAINPID User=opendkim Group=opendkim [Install] WantedBy=multi-user.target OpenDKIM-rel-opendkim-2-11-0-Beta2/copyright-check000077500000000000000000000005711337314105200214710ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2011-2014, The Trusted Domain Project. All rights reserved. # YEAR=`date +%Y` LASTYEAR=$(($YEAR - 1)) for i in `git diff develop --name-only @{$LASTYEAR-12-31} | fgrep -v .jpg | fgrep -v contrib/ | fgrep -v m4/` do if test -f $i then if grep -q Copyright $i then if ! grep -q Copyright.\*$YEAR $i then echo $i fi fi fi done OpenDKIM-rel-opendkim-2-11-0-Beta2/docs/000077500000000000000000000000001337314105200174055ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/docs/.gitignore000066400000000000000000000000251337314105200213720ustar00rootroot00000000000000Makefile Makefile.in OpenDKIM-rel-opendkim-2-11-0-Beta2/docs/Makefile.am000066400000000000000000000002171337314105200214410ustar00rootroot00000000000000# Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = README.specs.html OpenDKIM-rel-opendkim-2-11-0-Beta2/docs/README.specs.html000066400000000000000000000103131337314105200223420ustar00rootroot00000000000000 OpenDKIM Reference Documentation

This page includes links to all standards reference documentation on which OpenDKIM is built.

DKIM and Related Protocols

RFC6376: DomainKeys Identified Mail (DKIM) Signatures [DRAFT STANDARD]
RFC5617: DKIM Author Domain Signing Practices [PROPOSED STANDARD]
DKIM Implementation Report
RFC4686: Analysis of Threats Motivating DomainKeys Identified Mail [INFORMATIONAL]
RFC5016: Requirements for a DomainKeys Identified Mail (DKIM) Signing Practices Protocol [INFORMATIONAL]
RFC5585: DomainKeys Identified Mail (DKIM) Service Overview [INFORMATIONAL]
RFC5863: DomainKeys Identified Mail (DKIM) Development, Deployment, and Operations [INFORMATIONAL]
RFC6377: DomainKeys Identified Mail (DKIM) and Mailing Lists [BEST CURRENT PRACTICE]
RFC6541: DomainKeys Identified Mail (DKIM) Authorized Third-Party Signatures [EXPERIMENTAL]
Extensions to DKIM for Failure Reporting [PROPOSED STANDARD]

Email Format

RFC5322: Internet Message Format [DRAFT STANDARD]

Reporting Authentication Results

RFC5451: Message Header Field for Indicating Message Authentication Status [PROPOSED STANDARD]
RFC6008: Authentication-Results Registration for Differentiating among Cryptographic Results [PROPOSED STANDARD]
RFC6212: Authentication-Results Registration for Vouch by Reference Results [PROPOSED STANDARD]
RFC6577: Authentication-Results Registration Update for Sender Policy Framework (SPF) Results [PROPOSED STANDARD]

Abuse Reporting

RFC5965: An Extensible Format for Email Feedback Reports [PROPOSED STANDARD]
RFC6591: Authentication Failure Reporting Using the Abuse Reporting Format [PROPOSED STANDARD]
Creation and Use of Email Feedback Reports: An Applicability Statement for the Abuse Reporting Format (ARF)

Reputation

A Model for Reputation Reporting
A Media Type for Reputation Interchange
Reputation Data Interchange using HTTP and JSON
A Reputation Response Set for Email Identifiers

Other Specifications

RFC2254: The String Representation of LDAP Search Filters [PROPOSED STANDARD]
RFC3447: Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography Specifications Version 2.1 [INFORMATIONAL]
RFC5518: Vouch By Reference [PROPOSED STANDARD]
RFC6522: The Multipart/Report Media Type for the Reporting of Mail System Administrative Messages [STANDARD]
RFC6570: URI Template [PROPOSED STANDARD]
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/000077500000000000000000000000001337314105200207525ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/.gitignore000066400000000000000000000006631337314105200227470ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno *.gmon *.info *.prof t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure configure.scan aclocal.m4 depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile symbols.map .libs .deps *.core core description.txt description.html *.core OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/Makefile.am000066400000000000000000000033271337314105200230130ustar00rootroot00000000000000# Copyright (c) 2010-2014, The Trusted Domain Project. All rights reserved. SUBDIRS=tests docs if DEBUG AM_CFLAGS = -g endif LDADD = ./libopendkim.la lib_LTLIBRARIES = libopendkim.la libopendkim_la_SOURCES = base32.c base64.c dkim-atps.c dkim-cache.c dkim-canon.c dkim-dns.c dkim-keys.c dkim-mailparse.c dkim-report.c dkim-tables.c dkim-test.c dkim-util.c dkim.c util.c base64.h dkim-cache.h dkim-canon.h dkim-dns.h dkim-internal.h dkim-keys.h dkim-mailparse.h dkim-report.h dkim-tables.h dkim-test.h dkim-types.h dkim-util.h dkim.h util.h libopendkim_la_CPPFLAGS = $(LIBCRYPTO_CPPFLAGS) libopendkim_la_CFLAGS = $(LIBCRYPTO_INCDIRS) $(LIBOPENDKIM_INC) $(COV_CFLAGS) libopendkim_la_LDFLAGS = -no-undefined $(LIBCRYPTO_LIBDIRS) $(COV_LDFLAGS) -version-info $(LIBOPENDKIM_VERSION_INFO) libopendkim_la_LIBADD = $(LIBOPENDKIM_LIBS) $(LIBCRYPTO_LDADD) $(COV_LIBADD) if !ALL_SYMBOLS libopendkim_la_DEPENDENCIES = symbols.map libopendkim_la_LDFLAGS += -export-symbols symbols.map endif if RPATH libopendkim_la_LDFLAGS += -rpath $(libdir) endif libopendkim_includedir = $(includedir)/opendkim libopendkim_include_HEADERS = dkim.h pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = opendkim.pc if USE_DB_LIBOPENDKIM libopendkim_la_CPPFLAGS += -I$(LIBDB_INCDIRS) libopendkim_la_LDFLAGS += $(LIBDB_LIBDIRS) libopendkim_la_LIBADD += $(LIBDB_LIBS) endif if USE_TRE libopendkim_la_CFLAGS += $(LIBTRE_CPPFLAGS) libopendkim_la_LIBADD += $(LIBTRE_LIBS) endif DISTCLEANFILES=symbols.map *.gcno *.gcda symbols.map: $(libopendkim_include_HEADERS) grep '^extern' $? | \ awk '{ for (c = 1; c <= NF; c++) if ($$c ~ /dkim_/) { print $$c; break; } }' | \ sed -e s/\[\*\;\]//g -e s/\[\\\[\\\]\]//g | \ sort -u -o $@ MOSTLYCLEANFILES=symbols.map *.gcno *.gcda OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/README000066400000000000000000000020771337314105200216400ustar00rootroot00000000000000 ENVIRONMENT VARIABLES ===================== The following environment variables are checked and have some impact on what libdkim does: DKIM_TMPDIR directory in which temporary files are created; default is /tmp SELF-TEST ========= A number of self-test programs are included here for unit-testing the library. To run them, type "make check". A brief description of each test will be provided before its result. If the description is followed by the word SKIPPED, it means support for the function (e.g. an external library) to be tested was not available at compile-time and the test was not run. CRYPTO LIBRARIES ================ Cryptography libraries, such as openssl and gnutls, that can be used with libopendkim may have initialization requirements. libopendkim will not initialize these libraries for you, as doing so may interfere with other aspects of the application calling this library. It is therefore the responsibility of the calling application to initailize the crypto library before attempting DKIM signing or validation, or unexpected errors can occur. OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/base32.c000066400000000000000000000103001337314105200221670ustar00rootroot00000000000000/* ** Copyright (c) 2006-2009 Bjorn Andersson , ** Erik Ekman ** Mostly rewritten 2009 J.A.Bezemer@opensourcepartners.nl ** ** Permission to use, copy, modify, and distribute this software for any ** purpose with or without fee is hereby granted, provided that the above ** copyright notice and this permission notice appear in all copies. ** ** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ** WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ** MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ** ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ** WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ** ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ** OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ** ** Portions Copyright (c) 2010-2012, The Trusted Domain Project. ** All rights reserved. */ #include #include #include #include "dkim.h" #define BLKSIZE_RAW 5 #define BLKSIZE_ENC 8 static const char cb32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; /* ** DKIM_BASE32_ENCODE -- encode a string using base32 ** ** Parameters: ** buf -- destination buffer ** buflen -- in: bytes available at buf ** out: bytes used from "data" ** data -- pointer to data to encode ** size -- bytes at "data" to encode ** ** Return value: ** Length of encoding. ** ** Notes: ** buf should be at least a byte more than *buflen to hold the trailing ** '\0'. ** ** *buflen is updated to count the number of bytes read from "data". */ int dkim_base32_encode(char *buf, size_t *buflen, const void *data, size_t size) { unsigned int lastbits; unsigned int padding; int iout = 0; int iin = 0; unsigned char *udata; udata = (unsigned char *) data; for (;;) { if (iout >= *buflen || iin >= size) break; buf[iout] = cb32[((udata[iin] & 0xf8) >> 3)]; iout++; if (iout >= *buflen || iin >= size) { iout--; /* previous char is useless */ break; } buf[iout] = cb32[((udata[iin] & 0x07) << 2) | ((iin + 1 < size) ? ((udata[iin + 1] & 0xc0) >> 6) : 0)]; iin++; /* 0 complete, iin = 1 */ iout++; if (iout >= *buflen || iin >= size) break; buf[iout] = cb32[((udata[iin] & 0x3e) >> 1)]; iout++; if (iout >= *buflen || iin >= size) { iout--; /* previous char is useless */ break; } buf[iout] = cb32[((udata[iin] & 0x01) << 4) | ((iin + 1 < size) ? ((udata[iin + 1] & 0xf0) >> 4) : 0)]; iin++; /* 1 complete, iin = 2 */ iout++; if (iout >= *buflen || iin >= size) break; buf[iout] = cb32[((udata[iin] & 0x0f) << 1) | ((iin + 1 < size) ? ((udata[iin + 1] & 0x80) >> 7) : 0)]; iin++; /* 2 complete, iin = 3 */ iout++; if (iout >= *buflen || iin >= size) break; buf[iout] = cb32[((udata[iin] & 0x7c) >> 2)]; iout++; if (iout >= *buflen || iin >= size) { iout--; /* previous char is useless */ break; } buf[iout] = cb32[((udata[iin] & 0x03) << 3) | ((iin + 1 < size) ? ((udata[iin + 1] & 0xe0) >> 5) : 0)]; iin++; /* 3 complete, iin = 4 */ iout++; if (iout >= *buflen || iin >= size) break; buf[iout] = cb32[((udata[iin] & 0x1f))]; iin++; /* 4 complete, iin = 5 */ iout++; } /* append padding */ lastbits = (size * 8) % 40; if (lastbits == 0) padding = 0; else if (lastbits == 8) padding = 6; else if (lastbits == 16) padding = 4; else if (lastbits == 24) padding = 3; else /* (lastbits == 32) */ padding = 1; while (padding > 0 && iout < *buflen) { buf[iout++] = '='; padding--; } /* ensure NULL termination */ buf[iout] = '\0'; /* store number of bytes from data that was used */ *buflen = iin; return iout; } #ifdef TEST #include int main(int argc, char **argv) { int x; size_t buflen; SHA_CTX sha; char buf[128]; unsigned char shaout[SHA_DIGEST_LENGTH]; memset(buf, '\0', sizeof buf); buflen = sizeof buf; SHA1_Init(&sha); SHA1_Update(&sha, argv[1], strlen(argv[1])); SHA1_Final(shaout, &sha); x = dkim_base32_encode(buf, &buflen, shaout, SHA_DIGEST_LENGTH); printf("%s (%d)\n", buf, x); return 0; } #endif /* TEST */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/base64.c000066400000000000000000000102001337314105200221730ustar00rootroot00000000000000/* ** Copyright (c) 2005, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. */ /* system includes */ #include #include /* libopendkim includes */ #include "base64.h" /* base64 alphabet */ static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* base64 decode stuff */ static int decoder[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; #ifndef NULL # define NULL 0 #endif /* ! NULL */ /* ** DKIM_BASE64_DECODE -- decode a base64 blob ** ** Parameters: ** str -- string to decide ** buf -- where to write it ** buflen -- bytes available at "buf" ** ** Return value: ** >= 0 -- success; length of what was decoded is returned ** -1 -- corrupt ** -2 -- not enough space at "buf" */ int dkim_base64_decode(u_char *str, u_char *buf, size_t buflen) { int n = 0; int bits = 0; int char_count = 0; u_char *c; assert(str != NULL); assert(buf != NULL); for (c = str; *c != '=' && *c != '\0'; c++) { /* end padding */ if (*c == '=' || *c == '\0') break; /* skip stuff not part of the base64 alphabet (RFC2045) */ if (!((*c >= 'A' && *c <= 'Z') || (*c >= 'a' && *c <= 'z') || (*c >= '0' && *c <= '9') || (*c == '+') || (*c == '/'))) continue; /* everything else gets decoded */ bits += decoder[(int) *c]; char_count++; if (n + 3 > buflen) return -2; if (char_count == 4) { buf[n++] = (bits >> 16); buf[n++] = ((bits >> 8) & 0xff); buf[n++] = (bits & 0xff); bits = 0; char_count = 0; } else { bits <<= 6; } } /* XXX -- don't bother checking for proper termination (for now) */ /* process trailing data, if any */ switch (char_count) { case 0: break; case 1: /* base64 decoding incomplete; at least two bits missing */ return -1; case 2: if (n + 1 > buflen) return -2; buf[n++] = (bits >> 10); break; case 3: if (n + 2 > buflen) return -2; buf[n++] = (bits >> 16); buf[n++] = ((bits >> 8) & 0xff); break; } return n; } /* ** DKIM_BASE64_ENCODE -- encode base64 data ** ** Parameters: ** data -- data to encode ** datalen -- bytes at "data" to encode ** buf -- where to write the encoding ** buflen -- bytes available at "buf" ** ** Return value: ** >= 0 -- success; number of bytes written to "buf" returned ** -1 -- failure (not enough space at "buf") */ int dkim_base64_encode(u_char *data, size_t datalen, u_char *buf, size_t buflen) { int bits; int c; int char_count; size_t n; assert(data != NULL); assert(buf != NULL); bits = 0; char_count = 0; n = 0; for (c = 0; c < datalen; c++) { bits += data[c]; char_count++; if (char_count == 3) { if (n + 4 > buflen) return -1; buf[n++] = alphabet[bits >> 18]; buf[n++] = alphabet[(bits >> 12) & 0x3f]; buf[n++] = alphabet[(bits >> 6) & 0x3f]; buf[n++] = alphabet[bits & 0x3f]; bits = 0; char_count = 0; } else { bits <<= 8; } } if (char_count != 0) { if (n + 4 > buflen) return -1; bits <<= 16 - (8 * char_count); buf[n++] = alphabet[bits >> 18]; buf[n++] = alphabet[(bits >> 12) & 0x3f]; if (char_count == 1) { buf[n++] = '='; buf[n++] = '='; } else { buf[n++] = alphabet[(bits >> 6) & 0x3f]; buf[n++] = '='; } } return n; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/base64.h000066400000000000000000000007561337314105200222170ustar00rootroot00000000000000/* ** Copyright (c) 2005 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _BASE64_H_ #define _BASE64_H_ /* system includes */ #include /* prototypes */ extern int dkim_base64_decode(u_char *str, u_char *buf, size_t buflen); extern int dkim_base64_encode(u_char *data, size_t datalen, u_char *buf, size_t buflen); #endif /* ! _BASE64_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-atps.c000066400000000000000000000243211337314105200230110ustar00rootroot00000000000000/* ** Copyright (c) 2010-2012, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include /* libopendkim includes */ #include "dkim.h" #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-tables.h" #include "util.h" #ifdef USE_GNUTLS /* GnuTLS includes */ # include # include # ifndef SHA_DIGEST_LENGTH # define SHA_DIGEST_LENGTH 20 # endif /* ! SHA_DIGEST_LENGTH */ # ifndef SHA256_DIGEST_LENGTH # define SHA256_DIGEST_LENGTH 32 # endif /* ! SHA256_DIGEST_LENGTH */ #else /* USE_GNUTLS */ /* openssl includes */ # include #endif /* USE_GNUTLS */ /* prototypes */ extern void dkim_error __P((DKIM *, const char *, ...)); /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ #ifndef T_RRSIG # define T_RRSIG 46 #endif /* ! T_RRSIG */ #ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ! MAX */ #define DKIM_ATPS_QUERYLENGTH 64 #define DKIM_ATPS_VALID "v=ATPS1" #ifdef SHA256_DIGEST_LENGTH # define MAXDIGEST MAX(SHA_DIGEST_LENGTH, SHA256_DIGEST_LENGTH) #else /* SHA256_DIGEST_LENGTH */ # define MAXDIGEST SHA_DIGEST_LENGTH #endif /* SHA256_DIGEST_LENGTH */ /* ** DKIM_ATPS_CHECK -- check for Authorized Third Party Signing ** ** Parameters: ** dkim -- DKIM message handle ** sig -- signature information handle ** timeout -- timeout (can be NULL) ** res -- ATPS result code ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_atps_check(DKIM *dkim, DKIM_SIGINFO *sig, struct timeval *timeout, dkim_atps_t *res) { #ifdef _FFR_ATPS int status; int qdcount; int ancount; int class; int type; int error; int n; int hash = DKIM_HASHTYPE_UNKNOWN; int diglen; #ifdef USE_GNUTLS int ghash; #endif /* USE_GNUTLS */ unsigned int c; #ifdef QUERY_CACHE uint32_t ttl; #endif /* QUERY_CACHE */ size_t buflen; size_t anslen; DKIM_LIB *lib; u_char *fdomain; u_char *sdomain; u_char *adomain; u_char *txtfound = NULL; u_char *ahash = NULL; void *qh; u_char *p; u_char *cp; u_char *eom; #ifdef USE_GNUTLS gnutls_hash_hd_t ctx; #else /* USE_GNUTLS */ SHA_CTX ctx; # ifdef HAVE_SHA256 SHA256_CTX ctx2; # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ struct timeval to; HEADER hdr; u_char ansbuf[MAXPACKET]; u_char digest[MAXDIGEST]; u_char b32[DKIM_ATPS_QUERYLENGTH + 1]; u_char query[DKIM_MAXHOSTNAMELEN + 1]; u_char buf[BUFRSZ + 1]; #endif /* _FFR_ATPS */ assert(dkim != NULL); assert(sig != NULL); assert(res != NULL); #ifdef _FFR_ATPS lib = dkim->dkim_libhandle; sdomain = dkim_sig_getdomain(sig); fdomain = dkim_getdomain(dkim); adomain = dkim_sig_gettagvalue(sig, FALSE, "atps"); ahash = dkim_sig_gettagvalue(sig, FALSE, "atpsh"); if (sdomain == NULL || fdomain == NULL || adomain == NULL || ahash == NULL || strcasecmp(adomain, fdomain) != 0) return DKIM_STAT_INVALID; /* confirm it requested a hash we know how to do */ if (strcasecmp(ahash, "none") != 0) { hash = dkim_name_to_code(hashes, ahash); if (hash == -1) return DKIM_STAT_INVALID; } switch (hash) { case DKIM_HASHTYPE_SHA1: diglen = SHA_DIGEST_LENGTH; break; # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: diglen = SHA256_DIGEST_LENGTH; break; # endif /* HAVE_SHA256 */ case DKIM_HASHTYPE_UNKNOWN: break; default: assert(0); break; } if (hash != DKIM_HASHTYPE_UNKNOWN) { /* construct a hash of the signing domain */ # ifdef USE_GNUTLS switch (hash) { case DKIM_HASHTYPE_SHA1: ghash = GNUTLS_DIG_SHA1; break; case DKIM_HASHTYPE_SHA256: ghash = GNUTLS_DIG_SHA256; break; default: assert(0); break; } if (gnutls_hash_init(&ctx, ghash) != 0 || gnutls_hash(ctx, sdomain, strlen(sdomain)) != 0) return DKIM_STAT_INTERNAL; gnutls_hash_deinit(ctx, digest); # else /* USE_GNUTLS */ switch (hash) { case DKIM_HASHTYPE_SHA1: SHA1_Init(&ctx); SHA1_Update(&ctx, sdomain, strlen(sdomain)); SHA1_Final(digest, &ctx); break; # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: SHA256_Init(&ctx2); SHA256_Update(&ctx2, sdomain, strlen(sdomain)); SHA256_Final(digest, &ctx2); break; # endif /* HAVE_SHA256 */ default: assert(0); break; } # endif /* USE_GNUTLS */ /* base32-encode the hash */ memset(b32, '\0', sizeof b32); buflen = sizeof b32; if (dkim_base32_encode(b32, &buflen, digest, diglen) >= DKIM_ATPS_QUERYLENGTH) return DKIM_STAT_INTERNAL; /* form the query */ snprintf(query, sizeof query, "%s._atps.%s", b32, fdomain); } else { /* form the query */ snprintf(query, sizeof query, "%s._atps.%s", sdomain, fdomain); } /* XXX -- add QUERY_CACHE support here */ if (lib->dkiml_dns_service == NULL && lib->dkiml_dns_init != NULL && lib->dkiml_dns_init(&lib->dkiml_dns_service) != 0) { *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } /* send it */ anslen = sizeof ansbuf; status = lib->dkiml_dns_start(lib->dkiml_dns_service, T_TXT, query, ansbuf, anslen, &qh); if (status != DKIM_DNS_SUCCESS) { *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } /* wait for the reply */ to.tv_sec = dkim->dkim_timeout; to.tv_usec = 0; status = lib->dkiml_dns_waitreply(lib->dkiml_dns_service, qh, timeout == NULL ? &to : timeout, &anslen, &error, NULL); (void) lib->dkiml_dns_cancel(lib->dkiml_dns_service, qh); if (status != DKIM_DNS_SUCCESS) { *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } /* decode the reply */ memcpy(&hdr, ansbuf, sizeof hdr); cp = (u_char *) &ansbuf + HFIXEDSZ; eom = (u_char *) &ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) &ansbuf, eom, cp, (char *) query, sizeof query); if ((n = dn_skipname(cp, eom)) < 0) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_TXT || class != C_IN) { dkim_error(dkim, "'%s' unexpected reply type/class", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } if (hdr.rcode == NXDOMAIN) { *res = DKIM_ATPS_NOTFOUND; return DKIM_STAT_OK; } /* if truncated, we can't do it */ if (dkim_check_dns_reply(ansbuf, anslen, C_IN, T_TXT) == 1) { dkim_error(dkim, "'%s' reply truncated", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) { *res = DKIM_ATPS_NOTFOUND; return DKIM_STAT_OK; } /* ** Extract the data from the first TXT answer. */ while (--ancount >= 0 && cp < eom) { /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) &ansbuf, eom, cp, (RES_UNC_T) query, sizeof query)) < 0) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } GETSHORT(type, cp); GETSHORT(class, cp); #ifdef QUERY_CACHE /* get the TTL */ GETLONG(ttl, cp); #else /* QUERY_CACHE */ /* skip the TTL */ cp += INT32SZ; #endif /* QUERY_CACHE */ /* skip CNAME if found; assume it was resolved */ if (type == T_CNAME) { char chost[DKIM_MAXHOSTNAMELEN + 1]; n = dn_expand((u_char *) &ansbuf, eom, cp, chost, DKIM_MAXHOSTNAMELEN); cp += n; continue; } else if (type == T_RRSIG) { /* get payload length */ if (cp + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } GETSHORT(n, cp); cp += n; continue; } else if (type != T_TXT) { dkim_error(dkim, "'%s' reply was unexpected type %d", query, type); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } if (txtfound != NULL) { dkim_error(dkim, "multiple DNS replies for '%s'", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_MULTIDNSREPLY; } /* remember where this one started */ txtfound = cp; /* get payload length */ if (cp + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } GETSHORT(n, cp); /* move forward for now */ cp += n; } /* if ancount went below 0, there were no good records */ if (txtfound == NULL) { dkim_error(dkim, "'%s' reply was unresolved CNAME", query); *res = DKIM_ATPS_NOTFOUND; return DKIM_STAT_OK; } /* come back to the one we found */ cp = txtfound; /* get payload length */ if (cp + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } GETSHORT(n, cp); if (cp + n > eom) { dkim_error(dkim, "'%s' reply corrupt", query); *res = DKIM_ATPS_UNKNOWN; return DKIM_STAT_CANTVRFY; } /* extract the payload */ memset(buf, '\0', buflen); p = buf; eom = buf + buflen - 1; while (n > 0 && p < eom) { c = *cp++; n--; while (c > 0 && p < eom) { *p++ = *cp++; c--; n--; } } if (strcmp(buf, DKIM_ATPS_VALID) == 0) *res = DKIM_ATPS_FOUND; else *res = DKIM_ATPS_NOTFOUND; return DKIM_STAT_OK; #else /* ! _FFR_ATPS */ return DKIM_STAT_NOTIMPLEMENT; #endif /* ! _FFR_ATPS */ } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-cache.c000066400000000000000000000257071337314105200231160ustar00rootroot00000000000000/* ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, 2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" #ifdef QUERY_CACHE /* system includes */ #include #include #include #include #include #include #include #include #include #include /* libdb includes */ #include /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-cache.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* limits, macros, etc. */ #define BUFRSZ 1024 #define DB_MODE (S_IRUSR|S_IWUSR) #ifndef DB_NOTFOUND # define DB_NOTFOUND 1 #endif /* ! DB_NOTFOUND */ #ifndef DB_VERSION_MAJOR # define DB_VERSION_MAJOR 1 #endif /* ! DB_VERSION_MAJOR */ #define DB_VERSION_CHECK(x,y,z) ((DB_VERSION_MAJOR == (x) && \ DB_VERSION_MINOR == (y) && \ DB_VERSION_PATCH >= (z)) || \ (DB_VERSION_MAJOR == (x) && \ DB_VERSION_MINOR > (y)) || \ DB_VERSION_MAJOR > (x)) /* data types */ struct dkim_cache_entry { int cache_ttl; time_t cache_when; char cache_data[BUFRSZ + 1]; }; /* globals */ static pthread_mutex_t cache_stats_lock; /* stats lock */ static u_int c_hits = 0; /* cache hits */ static u_int c_queries = 0; /* cache queries */ static u_int c_expired = 0; /* expired cache hits */ static pthread_mutex_t cache_lock; /* cache lock */ /* ** DKIM_CACHE_INIT -- initialize an on-disk cache of entries ** ** Parameters: ** err -- error code (returned) ** tmpdir -- temporary directory to use (may be NULL) ** ** Return value: ** A DB handle referring to the cache, or NULL on error. */ DB * dkim_cache_init(int *err, char *tmpdir) { int status = 0; DB *cache = NULL; c_hits = 0; c_queries = 0; c_expired = 0; (void) pthread_mutex_init(&cache_stats_lock, NULL); (void) pthread_mutex_init(&cache_lock, NULL); #if DB_VERSION_CHECK(3,0,0) status = db_create(&cache, NULL, 0); if (status == 0) { # if DB_VERSION_CHECK(4,2,0) /* tell libdb which temporary directory to use */ if (tmpdir != NULL && tmpdir[0] != '\0') { DB_ENV *env = NULL; # if DB_VERSION_CHECK(4,3,0) env = cache->get_env(cache); # else /* DB_VERSION_CHECK(4,3,0) */ (void) cache->get_env(cache, &env); # endif /* DB_VERISON_CHECK(4,3,0) */ if (env != NULL) (void) env->set_tmp_dir(env, tmpdir); } # endif /* DB_VERISON_CHECK(4,2,0) */ # if DB_VERSION_CHECK(4,1,25) status = cache->open(cache, NULL, NULL, NULL, DB_HASH, DB_CREATE, DB_MODE); # else /* DB_VERSION_CHECK(4,1,25) */ status = cache->open(cache, NULL, NULL, DB_HASH, DB_CREATE, DB_MODE); # endif /* DB_VERSION_CHECK(4,1,25) */ } #elif DB_VERSION_CHECK(2,0,0) status = db_open(NULL, DB_HASH, DB_CREATE, DB_MODE, NULL, NULL, &cache); #else /* ! DB_VERSION_CHECK(2,0,0) */ cache = dbopen(NULL, (O_CREAT|O_RDWR), DB_MODE, DB_HASH, NULL); if (cache == NULL) status = errno; #endif /* DB_VERSION_CHECK */ if (status != 0) { if (err != NULL) *err = status; return NULL; } return cache; } /* ** DKIM_CACHE_QUERY -- query an on-disk cache of entries ** ** Parameters: ** db -- DB handle referring to the cache ** str -- key to query ** ttl -- time-to-live; ignore any record older than this; if 0, apply ** the TTL in the record ** buf -- buffer into which to write any cached data found ** buflen -- number of bytes at "buffer" (returned); caller should set ** this to the maximum space available and use the returned ** value as the length of the data returned ** err -- error code (returned) ** ** Return value: ** -1 -- error; caller should check "err" ** 0 -- no error; record found and data returned ** 1 -- no data found or data has expired */ int dkim_cache_query(DB *db, char *str, int ttl, char *buf, size_t *buflen, int *err) { int status; time_t now; DBT q; DBT d; struct dkim_cache_entry ce; assert(db != NULL); assert(str != NULL); assert(buf != NULL); assert(err != NULL); memset(&q, '\0', sizeof q); memset(&d, '\0', sizeof d); q.data = str; q.size = strlen(q.data); #if DB_VERSION_CHECK(2,0,0) d.flags = DB_DBT_USERMEM; d.data = (void *) &ce; d.ulen = sizeof ce; #endif /* DB_VERSION_CHECK(2,0,0) */ (void) time(&now); pthread_mutex_lock(&cache_stats_lock); c_queries++; pthread_mutex_unlock(&cache_stats_lock); pthread_mutex_lock(&cache_lock); #if DB_VERSION_CHECK(2,0,0) status = db->get(db, NULL, &q, &d, 0); #else /* DB_VERSION_CHECK(2,0,0) */ status = db->get(db, &q, &d, 0); #endif /* DB_VERSION_CHECK(2,0,0) */ pthread_mutex_unlock(&cache_lock); if (status == 0) { #if !DB_VERSION_CHECK(2,0,0) memset(&ce, '\0', sizeof ce); memcpy(&ce, d.data, MIN(sizeof ce, d.size)); #endif /* ! DB_VERSION_CHECK(2,0,0) */ if (ttl != 0) ce.cache_ttl = ttl; if (ce.cache_when + ce.cache_ttl < now) { pthread_mutex_lock(&cache_stats_lock); c_expired++; pthread_mutex_unlock(&cache_stats_lock); return 1; } pthread_mutex_lock(&cache_stats_lock); c_hits++; pthread_mutex_unlock(&cache_stats_lock); strlcpy(buf, ce.cache_data, *buflen); *buflen = strlen(ce.cache_data); return 0; } else if (status != DB_NOTFOUND) { *err = status; return -1; } else { return 1; } } /* ** DKIM_CACHE_INSERT -- insert data into an on-disk cache of entries ** ** Parameters: ** db -- DB handle referring to the cache ** str -- key to insert ** data -- data to insert ** ttl -- time-to-live ** err -- error code (returned) ** ** Return value: ** -1 -- error; caller should check "err" ** 0 -- cache updated */ int dkim_cache_insert(DB *db, char *str, char *data, int ttl, int *err) { int status; time_t now; DBT q; DBT d; struct dkim_cache_entry ce; assert(db != NULL); assert(str != NULL); assert(data != NULL); assert(err != NULL); (void) time(&now); memset(&q, '\0', sizeof q); memset(&d, '\0', sizeof d); q.data = str; q.size = strlen(str); d.data = (void *) &ce; d.size = sizeof ce; ce.cache_when = now; ce.cache_ttl = ttl; strlcpy(ce.cache_data, data, sizeof ce.cache_data); pthread_mutex_lock(&cache_lock); #if DB_VERSION_CHECK(2,0,0) status = db->put(db, NULL, &q, &d, 0); #else /* DB_VERSION_CHECK(2,0,0) */ status = db->put(db, &q, &d, 0); #endif /* DB_VERSION_CHECK(2,0,0) */ pthread_mutex_unlock(&cache_lock); if (status == 0) { return 0; } else { *err = status; return -1; } } /* ** DKIM_CACHE_EXPIRE -- expire records in an on-disk cache of entries ** ** Parameters: ** db -- DB handle referring to the cache ** ttl -- time-to-live; delete any record older than this; if 0, apply ** the TTL in the record ** err -- error code (returned) ** ** Return value: ** -1 -- error; caller should check "err" ** otherwise -- count of deleted records */ int dkim_cache_expire(DB *db, int ttl, int *err) { #if !DB_VERSION_CHECK(2,0,0) bool first = TRUE; #endif /* ! DB_VERSION_CHECK(2,0,0) */ bool delete; int deleted = 0; int status; time_t now; #if DB_VERSION_CHECK(2,0,0) DBC *dbc; #endif /* DB_VERSION_CHECK(2,0,0) */ DBT q; DBT d; char name[DKIM_MAXHOSTNAMELEN + 1]; struct dkim_cache_entry ce; assert(db != NULL); assert(err != NULL); memset(&q, '\0', sizeof q); memset(&d, '\0', sizeof d); (void) time(&now); pthread_mutex_lock(&cache_lock); #if DB_VERSION_CHECK(2,0,0) status = db->cursor(db, NULL, &dbc, 0); if (status != 0) { *err = status; pthread_mutex_unlock(&cache_lock); return -1; } #endif /* DB_VERSION_CHECK(2,0,0) */ for (;;) { memset(name, '\0', sizeof name); memset(&ce, '\0', sizeof ce); #if DB_VERSION_CHECK(3,0,0) q.data = name; q.flags = DB_DBT_USERMEM; q.ulen = sizeof name; #endif /* DB_VERSION_CHECK(3,0,0) */ #if DB_VERSION_CHECK(3,0,0) d.data = (void *) &ce; d.flags = DB_DBT_USERMEM; d.ulen = sizeof ce; #endif /* DB_VERSION_CHECK(3,0,0) */ #if DB_VERSION_CHECK(2,0,0) status = dbc->c_get(dbc, &q, &d, DB_NEXT); if (status == DB_NOTFOUND) { break; } else if (status != 0) { *err = status; break; } #else /* DB_VERSION_CHECK(2,0,0) */ status = db->seq(db, &q, &d, first ? R_FIRST : R_NEXT); if (status == DB_NOTFOUND) { break; } else if (status != 0) { *err = status; break; } first = FALSE; memcpy(name, q.data, MIN(sizeof name, q.size)); memcpy((void *) &ce, d.data, MIN(sizeof ce, d.size)); #endif /* DB_VERSION_CHECK(2,0,0) */ delete = FALSE; if (ttl == 0) { if (ce.cache_when + ce.cache_ttl < now) delete = TRUE; } else { if (ce.cache_when + ttl < now) delete = TRUE; } if (delete) { #if DB_VERSION_CHECK(2,0,0) status = dbc->c_del(dbc, 0); #else /* DB_VERSION_CHECK(2,0,0) */ status = db->del(db, &q, R_CURSOR); #endif /* DB_VERSION_CHECK(2,0,0) */ if (status != 0) { *err = status; deleted = -1; break; } deleted++; } } #if DB_VERSION_CHECK(2,0,0) (void) dbc->c_close(dbc); #endif /* DB_VERSION_CHECK(2,0,0) */ pthread_mutex_unlock(&cache_lock); return deleted; } /* ** DKIM_CACHE_CLOSE -- close a cache database ** ** Parameters: ** db -- cache DB handle ** ** Return value: ** None. */ void dkim_cache_close(DB *db) { assert(db != NULL); #if DB_VERSION_CHECK(2,0,0) (void) db->close(db, 0); #else /* DB_VERSION_CHECK(2,0,0) */ (void) db->close(db); #endif /* DB_VERSION_CHECK(2,0,0) */ (void) pthread_mutex_destroy(&cache_lock); } /* ** DKIM_CACHE_STATS -- retrieve cache performance statistics ** ** Parameters: ** queries -- number of queries handled (returned) ** hits -- number of cache hits (returned) ** expired -- number of expired hits (returned) ** ** Return value: ** None. ** ** Notes: ** Any of the parameters may be NULL if the corresponding datum ** is not of interest. */ void dkim_cache_stats(DB *db, u_int *queries, u_int *hits, u_int *expired, u_int *keys, _Bool reset) { pthread_mutex_lock(&cache_stats_lock); if (queries != NULL) *queries = c_queries; if (hits != NULL) *hits = c_hits; if (expired != NULL) *expired = c_expired; if (keys != NULL) { #if DB_VERSION_CHECK(2,0,0) DB_HASH_STAT *sp; # if DB_VERSION_CHECK(4,3,0) if (db->stat(db, NULL, (void *) &sp, 0) != 0) # elif DB_VERSION_CHECK(4,0,0) if (db->stat(db, (void *) &sp, 0) != 0) # else /* DB_VERSION_CHECK(4,0,0) */ if (db->stat(db, (void *) &sp, NULL, 0) != 0) # endif /* DB_VERSION_CHECK(4,0,0) */ { *keys = (u_int) -1; } else { # if DB_VERSION_CHECK(3,0,0) *keys = sp->hash_nkeys; # else /* DB_VERSION_CHECK(3,0,0) */ *keys = sp->hash_nrecs; # endif /* DB_VERSION_CHECK(3,0,0) */ free(sp); } #else /* DB_VERSION_CHECK(2,0,0) */ *keys = (u_int) -1; #endif /* DB_VERSION_CHECK(2,0,0) */ } if (reset) { c_queries = 0; c_hits = 0; c_expired = 0; } pthread_mutex_unlock(&cache_stats_lock); } #endif /* QUERY_CACHE */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-cache.h000066400000000000000000000015001337314105200231040ustar00rootroot00000000000000/* ** Copyright (c) 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, 2013, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_CACHE_H_ #define _DKIM_CACHE_H_ #include "build-config.h" #include "dkim-internal.h" #ifdef QUERY_CACHE /* libdb includes */ #include /* prototypes */ extern void dkim_cache_close __P((DB *)); extern int dkim_cache_expire __P((DB *, int, int *)); extern DB *dkim_cache_init __P((int *, char *)); extern int dkim_cache_insert __P((DB *, char *, char *, int, int *)); extern int dkim_cache_query __P((DB *, char *, int, char *, size_t *, int *)); extern void dkim_cache_stats __P((DB *, u_int *, u_int *, u_int *, u_int *, _Bool)); #endif /* QUERY_CACHE */ #endif /* ! _DKIM_CACHE_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-canon.c000066400000000000000000001266251337314105200231520ustar00rootroot00000000000000/* ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* _REENTRANT */ /* system includes */ #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #ifdef USE_TRE # ifdef TRE_PRE_080 # include # else /* TRE_PRE_080 */ # include # ifndef TRE_USE_SYSTEM_REGEX_H # define regcomp tre_regcomp # define regexec tre_regexec # define regfree tre_regfree # endif /* TRE_USE_SYSTEM_REGEX_H */ # endif /* TRE_PRE_080 */ #else /* USE_TRE */ # include #endif /* USE_TRE */ /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-canon.h" #include "dkim-util.h" #include "util.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* definitions */ #define CRLF (u_char *) "\r\n" #define SP (u_char *) " " /* macros */ #define DKIM_ISWSP(x) ((x) == 011 || (x) == 040) #define DKIM_ISLWSP(x) ((x) == 011 || (x) == 012 || (x) == 015 || (x) == 040) /* prototypes */ extern void dkim_error __P((DKIM *, const char *, ...)); /* ========================= PRIVATE SECTION ========================= */ /* ** DKIM_CANON_FREE -- destroy a canonicalization ** ** Parameters: ** dkim -- DKIM handle ** canon -- canonicalization to destroy ** ** Return value: ** None. */ static void dkim_canon_free(DKIM *dkim, DKIM_CANON *canon) { assert(dkim != NULL); assert(canon != NULL); if (canon->canon_hash != NULL) { switch (canon->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { struct dkim_sha *sha; sha = (struct dkim_sha *) canon->canon_hash; if (sha->sha_tmpfd != -1) { close(sha->sha_tmpfd); sha->sha_tmpfd = -1; } gnutls_hash_deinit(sha->sha_hd, NULL); if (sha->sha_out != NULL) { DKIM_FREE(dkim, sha->sha_out); sha->sha_out = NULL; } break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) canon->canon_hash; if (sha1->sha1_tmpbio != NULL) { BIO_free(sha1->sha1_tmpbio); sha1->sha1_tmpfd = -1; sha1->sha1_tmpbio = NULL; } break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) canon->canon_hash; if (sha256->sha256_tmpbio != NULL) { BIO_free(sha256->sha256_tmpbio); sha256->sha256_tmpfd = -1; sha256->sha256_tmpbio = NULL; } break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); /* NOTREACHED */ } dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure, canon->canon_hash); } if (canon->canon_hashbuf != NULL) { dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure, canon->canon_hashbuf); } if (canon->canon_buf != NULL) dkim_dstring_free(canon->canon_buf); dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure, canon); } /* ** DKIM_CANON_WRITE -- write data to canonicalization stream(s) ** ** Parameters: ** canon -- DKIM_CANON handle ** buf -- buffer containing canonicalized data ** buflen -- number of bytes to consume ** ** Return value: ** None. */ static void dkim_canon_write(DKIM_CANON *canon, u_char *buf, size_t buflen) { assert(canon != NULL); if (canon->canon_remain != (ssize_t) -1) buflen = MIN(buflen, canon->canon_remain); canon->canon_wrote += buflen; if (buf == NULL || buflen == 0) return; assert(canon->canon_hash != NULL); switch (canon->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { struct dkim_sha *sha; sha = (struct dkim_sha *) canon->canon_hash; gnutls_hash(sha->sha_hd, buf, buflen); if (sha->sha_tmpfd != -1) (void) write(sha->sha_tmpfd, buf, buflen); break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) canon->canon_hash; SHA1_Update(&sha1->sha1_ctx, buf, buflen); if (sha1->sha1_tmpbio != NULL) BIO_write(sha1->sha1_tmpbio, buf, buflen); break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) canon->canon_hash; SHA256_Update(&sha256->sha256_ctx, buf, buflen); if (sha256->sha256_tmpbio != NULL) BIO_write(sha256->sha256_tmpbio, buf, buflen); break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ } if (canon->canon_remain != (ssize_t) -1) canon->canon_remain -= buflen; } /* ** DKIM_CANON_BUFFER -- buffer for dkim_canon_write() ** ** Parameters: ** canon -- DKIM_CANON handle ** buf -- buffer containing canonicalized data ** buflen -- number of bytes to consume ** ** Return value: ** None. */ static void dkim_canon_buffer(DKIM_CANON *canon, u_char *buf, size_t buflen) { assert(canon != NULL); /* NULL buffer or 0 length means flush */ if (buf == NULL || buflen == 0) { if (canon->canon_hashbuflen > 0) { dkim_canon_write(canon, canon->canon_hashbuf, canon->canon_hashbuflen); canon->canon_hashbuflen = 0; } return; } /* not enough buffer space; write the buffer out */ if (canon->canon_hashbuflen + buflen > canon->canon_hashbufsize) { dkim_canon_write(canon, canon->canon_hashbuf, canon->canon_hashbuflen); canon->canon_hashbuflen = 0; } /* ** Now, if the input is bigger than the buffer, write it too; ** otherwise cache it. */ if (buflen >= canon->canon_hashbufsize) { dkim_canon_write(canon, buf, buflen); } else { memcpy(&canon->canon_hashbuf[canon->canon_hashbuflen], buf, buflen); canon->canon_hashbuflen += buflen; } } /* ** DKIM_CANON_HEADER_STRING -- canonicalize a header field ** ** Parameters: ** dstr -- dkim_dstring to use for output ** canon -- canonicalization mode to apply ** hdr -- header field input ** hdrlen -- bytes to process at "hdr" ** crlf -- write a CRLF at the end? ** ** Return value: ** A DKIM_STAT constant. */ DKIM_STAT dkim_canon_header_string(struct dkim_dstring *dstr, dkim_canon_t canon, unsigned char *hdr, size_t hdrlen, _Bool crlf) { _Bool space; u_char *p; u_char *tmp; u_char *end; u_char tmpbuf[BUFRSZ]; assert(dstr != NULL); assert(hdr != NULL); tmp = tmpbuf; end = tmpbuf + sizeof tmpbuf - 1; switch (canon) { case DKIM_CANON_SIMPLE: if (!dkim_dstring_catn(dstr, hdr, hdrlen) || (crlf && !dkim_dstring_catn(dstr, CRLF, 2))) return DKIM_STAT_NORESOURCE; break; case DKIM_CANON_RELAXED: /* process header field name (before colon) first */ for (p = hdr; p < hdr + hdrlen; p++) { /* ** Discard spaces before the colon or before the end ** of the first word. */ if (isascii(*p)) { /* discard spaces */ if (DKIM_ISLWSP(*p)) continue; /* convert to lowercase */ if (isupper(*p)) *tmp++ = tolower(*p); else *tmp++ = *p; } else { *tmp++ = *p; } /* reaching the end of the cache buffer, flush it */ if (tmp == end) { *tmp = '\0'; if (!dkim_dstring_catn(dstr, tmpbuf, tmp - tmpbuf)) return DKIM_STAT_NORESOURCE; tmp = tmpbuf; } if (*p == ':') { p++; break; } } /* skip all spaces before first word */ while (*p != '\0' && DKIM_ISLWSP(*p)) p++; space = FALSE; /* just saw a space */ for ( ; *p != '\0'; p++) { if (isascii(*p) && isspace(*p)) { /* mark that there was a space and continue */ space = TRUE; continue; } /* ** Any non-space marks the beginning of a word. ** If there's a stored space, use it up. */ if (space) { *tmp++ = ' '; /* flush buffer? */ if (tmp == end) { *tmp = '\0'; if (!dkim_dstring_catn(dstr, tmpbuf, tmp - tmpbuf)) return DKIM_STAT_NORESOURCE; tmp = tmpbuf; } space = FALSE; } /* copy the byte */ *tmp++ = *p; /* flush buffer? */ if (tmp == end) { *tmp = '\0'; if (!dkim_dstring_catn(dstr, tmpbuf, tmp - tmpbuf)) return DKIM_STAT_NORESOURCE; tmp = tmpbuf; } } /* flush any cached data */ if (tmp != tmpbuf) { *tmp = '\0'; if (!dkim_dstring_catn(dstr, tmpbuf, tmp - tmpbuf)) return DKIM_STAT_NORESOURCE; } if (crlf && !dkim_dstring_catn(dstr, CRLF, 2)) return DKIM_STAT_NORESOURCE; break; } return DKIM_STAT_OK; } /* ** DKIM_CANON_HEADER -- canonicalize a header and write it ** ** Parameters: ** dkim -- DKIM handle ** canon -- DKIM_CANON handle ** hdr -- header handle ** crlf -- write a CRLF at the end? ** ** Return value: ** A DKIM_STAT constant. */ static DKIM_STAT dkim_canon_header(DKIM *dkim, DKIM_CANON *canon, struct dkim_header *hdr, _Bool crlf) { DKIM_STAT status; assert(dkim != NULL); assert(canon != NULL); assert(hdr != NULL); if (dkim->dkim_canonbuf == NULL) { dkim->dkim_canonbuf = dkim_dstring_new(dkim, hdr->hdr_textlen, 0); if (dkim->dkim_canonbuf == NULL) return DKIM_STAT_NORESOURCE; } else { dkim_dstring_blank(dkim->dkim_canonbuf); } dkim_canon_buffer(canon, NULL, 0); status = dkim_canon_header_string(dkim->dkim_canonbuf, canon->canon_canon, hdr->hdr_text, hdr->hdr_textlen, crlf); if (status != DKIM_STAT_OK) return status; dkim_canon_buffer(canon, dkim_dstring_get(dkim->dkim_canonbuf), dkim_dstring_len(dkim->dkim_canonbuf)); return DKIM_STAT_OK; } /* ** DKIM_CANON_FLUSHBLANKS -- use accumulated blank lines in canonicalization ** ** Parameters: ** canon -- DKIM_CANON handle ** ** Return value: ** None. */ static void dkim_canon_flushblanks(DKIM_CANON *canon) { int c; assert(canon != NULL); for (c = 0; c < canon->canon_blanks; c++) dkim_canon_buffer(canon, CRLF, 2); canon->canon_blanks = 0; } /* ** DKIM_CANON_FIXCRLF -- rebuffer a body chunk, fixing "naked" CRs and LFs ** ** Parameters: ** dkim -- DKIM handle ** canon -- canonicalization being handled ** buf -- buffer to be fixed ** buflen -- number of bytes at "buf" ** ** Return value: ** A DKIM_STAT_* constant. ** ** Side effects: ** dkim->dkim_canonbuf will be initialized and used. */ static DKIM_STAT dkim_canon_fixcrlf(DKIM *dkim, DKIM_CANON *canon, u_char *buf, size_t buflen) { u_char prev; u_char *p; u_char *eob; assert(dkim != NULL); assert(canon != NULL); assert(buf != NULL); if (dkim->dkim_canonbuf == NULL) { dkim->dkim_canonbuf = dkim_dstring_new(dkim, buflen, 0); if (dkim->dkim_canonbuf == NULL) return DKIM_STAT_NORESOURCE; } else { dkim_dstring_blank(dkim->dkim_canonbuf); } eob = buf + buflen - 1; prev = canon->canon_lastchar; for (p = buf; p <= eob; p++) { if (*p == '\n' && prev != '\r') { /* fix a solitary LF */ dkim_dstring_catn(dkim->dkim_canonbuf, CRLF, 2); } else if (*p == '\r') { if (p < eob && *(p + 1) != '\n') /* fix a solitary CR */ dkim_dstring_catn(dkim->dkim_canonbuf, CRLF, 2); else /* CR at EOL, or CR followed by a LF */ dkim_dstring_cat1(dkim->dkim_canonbuf, *p); } else { /* something else */ dkim_dstring_cat1(dkim->dkim_canonbuf, *p); } prev = *p; } return DKIM_STAT_OK; } /* ========================= PUBLIC SECTION ========================= */ /* ** DKIM_CANON_INIT -- initialize all canonicalizations ** ** Parameters: ** dkim -- DKIM handle ** tmp -- make temp files? ** keep -- keep temp files? ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_canon_init(DKIM *dkim, _Bool tmp, _Bool keep) { int fd; DKIM_STAT status; DKIM_CANON *cur; assert(dkim != NULL); for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { cur->canon_hashbuf = DKIM_MALLOC(dkim, DKIM_HASHBUFSIZE); if (cur->canon_hashbuf == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", DKIM_HASHBUFSIZE); return DKIM_STAT_NORESOURCE; } cur->canon_hashbufsize = DKIM_HASHBUFSIZE; cur->canon_hashbuflen = 0; cur->canon_buf = dkim_dstring_new(dkim, BUFRSZ, 0); if (cur->canon_buf == NULL) return DKIM_STAT_NORESOURCE; switch (cur->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { struct dkim_sha *sha; sha = (struct dkim_sha *) DKIM_MALLOC(dkim, sizeof(struct dkim_sha)); if (sha == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_sha)); return DKIM_STAT_NORESOURCE; } memset(sha, '\0', sizeof(struct dkim_sha)); sha->sha_tmpfd = -1; /* XXX -- test for errors */ if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1) { (void) gnutls_hash_init(&sha->sha_hd, GNUTLS_DIG_SHA1); } else { (void) gnutls_hash_init(&sha->sha_hd, GNUTLS_DIG_SHA256); } if (sha->sha_hd == NULL) { DKIM_FREE(dkim, sha); return DKIM_STAT_INTERNAL; } if (tmp) { status = dkim_tmpfile(dkim, &fd, keep); if (status != DKIM_STAT_OK) { DKIM_FREE(dkim, sha); return status; } sha->sha_tmpfd = fd; } cur->canon_hash = sha; break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) DKIM_MALLOC(dkim, sizeof(struct dkim_sha1)); if (sha1 == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_sha1)); return DKIM_STAT_NORESOURCE; } memset(sha1, '\0', sizeof(struct dkim_sha1)); SHA1_Init(&sha1->sha1_ctx); if (tmp) { status = dkim_tmpfile(dkim, &fd, keep); if (status != DKIM_STAT_OK) { DKIM_FREE(dkim, sha1); return status; } sha1->sha1_tmpfd = fd; sha1->sha1_tmpbio = BIO_new_fd(fd, 1); } cur->canon_hash = sha1; break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) DKIM_MALLOC(dkim, sizeof(struct dkim_sha256)); if (sha256 == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_sha256)); return DKIM_STAT_NORESOURCE; } memset(sha256, '\0', sizeof(struct dkim_sha256)); SHA256_Init(&sha256->sha256_ctx); if (tmp) { status = dkim_tmpfile(dkim, &fd, keep); if (status != DKIM_STAT_OK) { DKIM_FREE(dkim, sha256); return status; } sha256->sha256_tmpfd = fd; sha256->sha256_tmpbio = BIO_new_fd(fd, 1); } cur->canon_hash = sha256; break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); } } return DKIM_STAT_OK; } /* ** DKIM_CANON_CLEANUP -- discard canonicalizations ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** None. */ void dkim_canon_cleanup(DKIM *dkim) { DKIM_CANON *cur; DKIM_CANON *next; assert(dkim != NULL); #ifdef _FFR_RESIGN if (dkim->dkim_resign != NULL && dkim->dkim_hdrbind) return; #endif /* _FFR_RESIGN */ cur = dkim->dkim_canonhead; while (cur != NULL) { next = cur->canon_next; #ifdef _FFR_RESIGN /* skip if resigning and body */ if (dkim->dkim_resign == NULL || cur->canon_hdr) dkim_canon_free(dkim, cur); #else /* _FFR_RESIGN */ dkim_canon_free(dkim, cur); #endif /* _FFR_RESIGN */ cur = next; } dkim->dkim_canonhead = NULL; } /* ** DKIM_ADD_CANON -- add a new canonicalization handle if needed ** ** Parameters: ** dkim -- verification handle ** hdr -- TRUE iff this is specifying a header canonicalization ** canon -- canonicalization mode ** hashtype -- hash type ** hdrlist -- for header canonicalization, the header list ** sighdr -- pointer to header being verified (NULL for signing) ** length -- for body canonicalization, the length limit (-1 == all) ** cout -- DKIM_CANON handle (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_add_canon(DKIM *dkim, _Bool hdr, dkim_canon_t canon, int hashtype, u_char *hdrlist, struct dkim_header *sighdr, ssize_t length, DKIM_CANON **cout) { DKIM_CANON *cur; DKIM_CANON *new; assert(dkim != NULL); assert(canon == DKIM_CANON_SIMPLE || canon == DKIM_CANON_RELAXED); if (dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256)) { assert(hashtype == DKIM_HASHTYPE_SHA1 || hashtype == DKIM_HASHTYPE_SHA256); } else { assert(hashtype == DKIM_HASHTYPE_SHA1); } if (!hdr) { for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { if (cur->canon_hdr || cur->canon_hashtype != hashtype || cur->canon_canon != canon) continue; if (length != cur->canon_length) continue; if (cout != NULL) *cout = cur; return DKIM_STAT_OK; } } new = (DKIM_CANON *) dkim_malloc(dkim->dkim_libhandle, dkim->dkim_closure, sizeof *new); if (new == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof *new); return DKIM_STAT_NORESOURCE; } new->canon_done = FALSE; new->canon_hdr = hdr; new->canon_canon = canon; new->canon_hashtype = hashtype; new->canon_hash = NULL; new->canon_wrote = 0; if (hdr) { new->canon_length = (ssize_t) -1; new->canon_remain = (ssize_t) -1; } else { new->canon_length = length; new->canon_remain = length; } new->canon_sigheader = sighdr; new->canon_hdrlist = hdrlist; new->canon_buf = NULL; new->canon_next = NULL; new->canon_blankline = TRUE; new->canon_blanks = 0; new->canon_bodystate = 0; new->canon_hashbuflen = 0; new->canon_hashbufsize = 0; new->canon_hashbuf = NULL; new->canon_lastchar = '\0'; if (dkim->dkim_canonhead == NULL) { dkim->dkim_canontail = new; dkim->dkim_canonhead = new; } else { dkim->dkim_canontail->canon_next = new; dkim->dkim_canontail = new; } if (cout != NULL) *cout = new; return DKIM_STAT_OK; } /* ** DKIM_CANON_SELECTHDRS -- choose headers to be included in canonicalization ** ** Parameters: ** dkim -- DKIM context in which this is performed ** hdrlist -- string containing headers that should be marked, separated ** by the ":" character ** ptrs -- array of header pointers (modified) ** nptr -- number of pointers available at "ptrs" ** ** Return value: ** Count of headers added to "ptrs", or -1 on error. ** ** Notes: ** Selects headers to be passed to canonicalization and the order in ** which this is done. "ptrs" is populated by pointers to headers ** in the order in which they should be fed to canonicalization. ** ** If any of the returned pointers is NULL, then a header named by ** "hdrlist" was not found. */ int dkim_canon_selecthdrs(DKIM *dkim, u_char *hdrlist, struct dkim_header **ptrs, int nptrs) { int c; int n; int m; int shcnt; size_t len; char *bar; char *ctx; u_char *colon; struct dkim_header *hdr; struct dkim_header **lhdrs; u_char **hdrs; assert(dkim != NULL); assert(ptrs != NULL); assert(nptrs != 0); /* if there are no headers named, use them all */ if (hdrlist == NULL) { n = 0; for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { if (n >= nptrs) { dkim_error(dkim, "too many headers (max %d)", nptrs); return -1; } ptrs[n] = hdr; n++; } return n; } if (dkim->dkim_hdrlist == NULL) { dkim->dkim_hdrlist = dkim_malloc(dkim->dkim_libhandle, dkim->dkim_closure, DKIM_MAXHEADER); if (dkim->dkim_hdrlist == NULL) { dkim_error(dkim, "unable to allocate %d bytes(s)", DKIM_MAXHEADER); return -1; } } strlcpy((char *) dkim->dkim_hdrlist, (char *) hdrlist, DKIM_MAXHEADER); /* mark all headers as not used */ for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) hdr->hdr_flags &= ~DKIM_HDR_SIGNED; n = dkim->dkim_hdrcnt * sizeof(struct dkim_header *); lhdrs = DKIM_MALLOC(dkim, n); if (lhdrs == NULL) return -1; memset(lhdrs, '\0', n); shcnt = 1; for (colon = dkim->dkim_hdrlist; *colon != '\0'; colon++) { if (*colon == ':') shcnt++; } n = sizeof(u_char *) * shcnt; hdrs = DKIM_MALLOC(dkim, n); if (hdrs == NULL) { (void) DKIM_FREE(dkim, lhdrs); return -1; } memset(hdrs, '\0', n); n = 0; /* make a split-out copy of hdrlist */ for (bar = strtok_r((char *) dkim->dkim_hdrlist, ":", &ctx); bar != NULL; bar = strtok_r(NULL, ":", &ctx)) { hdrs[n] = (u_char *) bar; n++; } /* for each named header, find the last unused one and use it up */ shcnt = 0; for (c = 0; c < n; c++) { lhdrs[shcnt] = NULL; len = MIN(DKIM_MAXHEADER, strlen((char *) hdrs[c])); while (len > 0 && DKIM_ISWSP(hdrs[c][len - 1])) len--; for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { if (hdr->hdr_flags & DKIM_HDR_SIGNED) continue; if (len == hdr->hdr_namelen && strncasecmp((char *) hdr->hdr_text, (char *) hdrs[c], len) == 0) lhdrs[shcnt] = hdr; } if (lhdrs[shcnt] != NULL) { lhdrs[shcnt]->hdr_flags |= DKIM_HDR_SIGNED; shcnt++; } } /* bounds check */ if (shcnt > nptrs) { dkim_error(dkim, "too many headers (found %d, max %d)", shcnt, nptrs); DKIM_FREE(dkim, lhdrs); DKIM_FREE(dkim, hdrs); return -1; } /* copy to the caller's buffers */ m = 0; for (c = 0; c < shcnt; c++) { if (lhdrs[c] != NULL) { ptrs[m] = lhdrs[c]; m++; } } DKIM_FREE(dkim, lhdrs); DKIM_FREE(dkim, hdrs); return m; } /* ** DKIM_CANON_RUNHEADERS -- run the headers through all header ** canonicalizations ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. ** ** Note: ** Header canonicalizations are finalized by this function when ** verifying. In signing mode, header canonicalizations are finalized ** by a subsequent call to dkim_canon_signature(). */ DKIM_STAT dkim_canon_runheaders(DKIM *dkim) { _Bool signing; u_char savechar; int c; int n; int in; int nhdrs = 0; int last = '\0'; DKIM_STAT status; u_char *tmp; u_char *end; DKIM_CANON *cur; u_char *p; struct dkim_header *hdr; struct dkim_header **hdrset; struct dkim_header tmphdr; u_char tmpbuf[BUFRSZ]; assert(dkim != NULL); tmp = tmpbuf; end = tmpbuf + sizeof tmpbuf - 1; n = dkim->dkim_hdrcnt * sizeof(struct dkim_header *); hdrset = DKIM_MALLOC(dkim, n); if (hdrset == NULL) return DKIM_STAT_NORESOURCE; if (dkim->dkim_hdrbuf == NULL) { dkim->dkim_hdrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (dkim->dkim_hdrbuf == NULL) { DKIM_FREE(dkim, hdrset); return DKIM_STAT_NORESOURCE; } } else { dkim_dstring_blank(dkim->dkim_hdrbuf); } for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { /* skip done hashes and those which are of the wrong type */ if (cur->canon_done || !cur->canon_hdr) continue; signing = (cur->canon_sigheader == NULL); /* clear header selection flags if verifying */ if (!signing) { if (cur->canon_hdrlist == NULL) { for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) hdr->hdr_flags |= DKIM_HDR_SIGNED; } else { for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) hdr->hdr_flags &= ~DKIM_HDR_SIGNED; memset(hdrset, '\0', n); /* do header selection */ nhdrs = dkim_canon_selecthdrs(dkim, cur->canon_hdrlist, hdrset, dkim->dkim_hdrcnt); if (nhdrs == -1) { dkim_error(dkim, "dkim_canon_selecthdrs() failed during canonicalization"); DKIM_FREE(dkim, hdrset); return DKIM_STAT_INTERNAL; } } } else { DKIM_LIB *lib; regex_t *hdrtest; lib = dkim->dkim_libhandle; if (dkim->dkim_hdrre != NULL) hdrtest = dkim->dkim_hdrre; else hdrtest = &lib->dkiml_hdrre; memset(hdrset, '\0', sizeof *hdrset); nhdrs = 0; /* tag headers to be signed */ for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { if (hdrtest == &lib->dkiml_hdrre && !lib->dkiml_signre) { tmp = dkim_dstring_get(dkim->dkim_hdrbuf); if (tmp[0] != '\0') { dkim_dstring_cat1(dkim->dkim_hdrbuf, ':'); } dkim_dstring_catn(dkim->dkim_hdrbuf, hdr->hdr_text, hdr->hdr_namelen); continue; } /* could be space, could be colon ... */ savechar = hdr->hdr_text[hdr->hdr_namelen]; /* terminate the header field name and test */ hdr->hdr_text[hdr->hdr_namelen] = '\0'; status = regexec(hdrtest, (char *) hdr->hdr_text, 0, NULL, 0); /* restore the character */ hdr->hdr_text[hdr->hdr_namelen] = savechar; if (status == 0) { tmp = dkim_dstring_get(dkim->dkim_hdrbuf); if (tmp[0] != '\0') { dkim_dstring_cat1(dkim->dkim_hdrbuf, ':'); } dkim_dstring_catn(dkim->dkim_hdrbuf, hdr->hdr_text, hdr->hdr_namelen); } else { assert(status == REG_NOMATCH); } } memset(hdrset, '\0', n); /* do header selection */ nhdrs = dkim_canon_selecthdrs(dkim, dkim_dstring_get(dkim->dkim_hdrbuf), hdrset, dkim->dkim_hdrcnt); if (nhdrs == -1) { dkim_error(dkim, "dkim_canon_selecthdrs() failed during canonicalization"); DKIM_FREE(dkim, hdrset); return DKIM_STAT_INTERNAL; } } /* canonicalize each marked header */ for (c = 0; c < nhdrs; c++) { if (hdrset[c] != NULL && (hdrset[c]->hdr_flags & DKIM_HDR_SIGNED) != 0) { status = dkim_canon_header(dkim, cur, hdrset[c], TRUE); if (status != DKIM_STAT_OK) { DKIM_FREE(dkim, hdrset); return status; } } } /* if signing, we can't do the rest of this yet */ if (cur->canon_sigheader == NULL) continue; /* ** We need to copy the DKIM-Signature: header being verified, ** minus the contents of the "b=" part, and include it in the ** canonicalization. However, skip this if no hashing was ** done. */ dkim_dstring_blank(dkim->dkim_hdrbuf); tmp = tmpbuf; n = 0; in = '\0'; for (p = cur->canon_sigheader->hdr_text; *p != '\0'; p++) { if (*p == ';') in = '\0'; if (in == 'b') { last = *p; continue; } if (in == '\0' && *p == '=') in = last; *tmp++ = *p; /* flush buffer? */ if (tmp == end) { *tmp = '\0'; if (!dkim_dstring_catn(dkim->dkim_hdrbuf, tmpbuf, tmp - tmpbuf)) { DKIM_FREE(dkim, hdrset); return DKIM_STAT_NORESOURCE; } tmp = tmpbuf; } last = *p; } /* flush anything cached */ if (tmp != tmpbuf) { *tmp = '\0'; if (!dkim_dstring_catn(dkim->dkim_hdrbuf, tmpbuf, tmp - tmpbuf)) { DKIM_FREE(dkim, hdrset); return DKIM_STAT_NORESOURCE; } } /* canonicalize */ tmphdr.hdr_text = dkim_dstring_get(dkim->dkim_hdrbuf); tmphdr.hdr_namelen = cur->canon_sigheader->hdr_namelen; tmphdr.hdr_colon = tmphdr.hdr_text + (cur->canon_sigheader->hdr_colon - cur->canon_sigheader->hdr_text); tmphdr.hdr_textlen = dkim_dstring_len(dkim->dkim_hdrbuf); tmphdr.hdr_flags = 0; tmphdr.hdr_next = NULL; if (cur->canon_canon == DKIM_CANON_RELAXED) dkim_lowerhdr(tmphdr.hdr_text); (void) dkim_canon_header(dkim, cur, &tmphdr, FALSE); dkim_canon_buffer(cur, NULL, 0); /* finalize */ switch (cur->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { int alg; struct dkim_sha *sha; sha = (struct dkim_sha *) cur->canon_hash; if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1) alg = GNUTLS_DIG_SHA1; else alg = GNUTLS_DIG_SHA256; sha->sha_outlen = gnutls_hash_get_len(alg); sha->sha_out = DKIM_MALLOC(dkim, sha->sha_outlen); if (sha->sha_out == NULL) { dkim_error(dkim, "unable to allocate %u bytes", sha->sha_outlen); return DKIM_STAT_NORESOURCE; } gnutls_hash_output(sha->sha_hd, sha->sha_out); break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) cur->canon_hash; SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx); if (sha1->sha1_tmpbio != NULL) (void) BIO_flush(sha1->sha1_tmpbio); break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) cur->canon_hash; SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx); if (sha256->sha256_tmpbio != NULL) (void) BIO_flush(sha256->sha256_tmpbio); break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); /* NOTREACHED */ } cur->canon_done = TRUE; } DKIM_FREE(dkim, hdrset); return DKIM_STAT_OK; } /* ** DKIM_CANON_SIGNATURE -- append a signature header when signing ** ** Parameters: ** dkim -- DKIM handle ** hdr -- header ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** Header canonicalizations are finalized by this function. */ DKIM_STAT dkim_canon_signature(DKIM *dkim, struct dkim_header *hdr) { DKIM_STAT status; DKIM_CANON *cur; struct dkim_header tmphdr; assert(dkim != NULL); assert(hdr != NULL); if (dkim->dkim_hdrbuf == NULL) { dkim->dkim_hdrbuf = dkim_dstring_new(dkim, DKIM_MAXHEADER, 0); if (dkim->dkim_hdrbuf == NULL) return DKIM_STAT_NORESOURCE; } else { dkim_dstring_blank(dkim->dkim_hdrbuf); } for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { /* skip done hashes and those which are of the wrong type */ if (cur->canon_done || !cur->canon_hdr) continue; /* prepare the data */ dkim_dstring_copy(dkim->dkim_hdrbuf, hdr->hdr_text); tmphdr.hdr_text = dkim_dstring_get(dkim->dkim_hdrbuf); tmphdr.hdr_namelen = hdr->hdr_namelen; tmphdr.hdr_colon = tmphdr.hdr_text + (hdr->hdr_colon - hdr->hdr_text); tmphdr.hdr_textlen = dkim_dstring_len(dkim->dkim_hdrbuf); tmphdr.hdr_flags = 0; tmphdr.hdr_next = NULL; if (cur->canon_canon == DKIM_CANON_RELAXED) dkim_lowerhdr(tmphdr.hdr_text); /* canonicalize the signature */ status = dkim_canon_header(dkim, cur, &tmphdr, FALSE); if (status != DKIM_STAT_OK) return status; dkim_canon_buffer(cur, NULL, 0); /* now close it */ switch (cur->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { int alg; struct dkim_sha *sha; sha = (struct dkim_sha *) cur->canon_hash; if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1) alg = GNUTLS_DIG_SHA1; else alg = GNUTLS_DIG_SHA256; sha->sha_outlen = gnutls_hash_get_len(alg); sha->sha_out = DKIM_MALLOC(dkim, sha->sha_outlen); if (sha->sha_out == NULL) { dkim_error(dkim, "unable to allocate %u bytes", sha->sha_outlen); return DKIM_STAT_NORESOURCE; } gnutls_hash_output(sha->sha_hd, sha->sha_out); if (sha->sha_tmpfd != -1) { close(sha->sha_tmpfd); sha->sha_tmpfd = -1; } break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) cur->canon_hash; SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx); if (sha1->sha1_tmpbio != NULL) (void) BIO_flush(sha1->sha1_tmpbio); break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) cur->canon_hash; SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx); if (sha256->sha256_tmpbio != NULL) (void) BIO_flush(sha256->sha256_tmpbio); break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); /* NOTREACHED */ } cur->canon_done = TRUE; } return DKIM_STAT_OK; } /* ** DKIM_CANON_MINBODY -- return number of bytes required to satisfy all ** canonicalizations ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** 0 -- all canonicalizations satisfied ** ULONG_MAX -- at least one canonicalization wants the whole message ** other -- bytes required to satisfy all canonicalizations */ u_long dkim_canon_minbody(DKIM *dkim) { u_long minbody = 0; DKIM_CANON *cur; assert(dkim != NULL); for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { /* skip done hashes and those which are of the wrong type */ if (cur->canon_done || cur->canon_hdr) continue; /* if this one wants the whole message, short-circuit */ if (cur->canon_remain == (ssize_t) -1) return ULONG_MAX; /* compare to current minimum */ minbody = MAX(minbody, (u_long) cur->canon_remain); } return minbody; } /* ** DKIM_CANON_BODYCHUNK -- run a body chunk through all body ** canonicalizations ** ** Parameters: ** dkim -- DKIM handle ** buf -- pointer to bytes to canonicalize ** buflen -- number of bytes to canonicalize ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_canon_bodychunk(DKIM *dkim, u_char *buf, size_t buflen) { _Bool fixcrlf; DKIM_STAT status; u_int wlen; DKIM_CANON *cur; size_t plen; u_char *p; u_char *wrote; u_char *eob; u_char *start; assert(dkim != NULL); dkim->dkim_bodylen += buflen; fixcrlf = (dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF); for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { /* skip done hashes and those which are of the wrong type */ if (cur->canon_done || cur->canon_hdr) continue; start = buf; plen = buflen; if (fixcrlf) { status = dkim_canon_fixcrlf(dkim, cur, buf, buflen); if (status != DKIM_STAT_OK) return status; start = dkim_dstring_get(dkim->dkim_canonbuf); plen = dkim_dstring_len(dkim->dkim_canonbuf); } eob = start + plen - 1; wrote = start; wlen = 0; switch (cur->canon_canon) { case DKIM_CANON_SIMPLE: for (p = start; p <= eob; p++) { if (*p == '\n') { if (cur->canon_lastchar == '\r') { if (cur->canon_blankline) { cur->canon_blanks++; } else if (wlen == 1 || p == start) { dkim_canon_buffer(cur, CRLF, 2); } else { dkim_canon_buffer(cur, wrote, wlen + 1); } wrote = p + 1; wlen = 0; cur->canon_blankline = TRUE; } } else { if (p == start && cur->canon_lastchar == '\r') { if (fixcrlf) { dkim_canon_buffer(cur, CRLF, 2); cur->canon_lastchar = '\n'; cur->canon_blankline = TRUE; } else { dkim_canon_buffer(cur, (u_char *) "\r", 1); } } if (*p != '\r') { if (cur->canon_blanks > 0) dkim_canon_flushblanks(cur); cur->canon_blankline = FALSE; } wlen++; } cur->canon_lastchar = *p; } if (wlen > 0 && wrote[wlen - 1] == '\r') wlen--; dkim_canon_buffer(cur, wrote, wlen); break; case DKIM_CANON_RELAXED: for (p = start; p <= eob; p++) { switch (cur->canon_bodystate) { case 0: if (DKIM_ISWSP(*p)) { cur->canon_bodystate = 1; } else if (*p == '\r') { cur->canon_bodystate = 2; } else { cur->canon_blankline = FALSE; dkim_dstring_cat1(cur->canon_buf, *p); cur->canon_bodystate = 3; } break; case 1: if (DKIM_ISWSP(*p)) { break; } else if (*p == '\r') { cur->canon_bodystate = 2; } else { dkim_canon_flushblanks(cur); dkim_canon_buffer(cur, SP, 1); cur->canon_blankline = FALSE; dkim_dstring_cat1(cur->canon_buf, *p); cur->canon_bodystate = 3; } break; case 2: if (fixcrlf || *p == '\n') { if (cur->canon_blankline) { cur->canon_blanks++; cur->canon_bodystate = 0; } else { dkim_canon_flushblanks(cur); dkim_canon_buffer(cur, dkim_dstring_get(cur->canon_buf), dkim_dstring_len(cur->canon_buf)); dkim_canon_buffer(cur, CRLF, 2); dkim_dstring_blank(cur->canon_buf); if (*p == '\n') { cur->canon_blankline = TRUE; cur->canon_bodystate = 0; } else if (*p == '\r') { cur->canon_blankline = TRUE; } else { if (DKIM_ISWSP(*p)) { cur->canon_bodystate = 1; } else { dkim_dstring_cat1(cur->canon_buf, *p); cur->canon_bodystate = 3; } } } } else if (*p == '\r') { cur->canon_blankline = FALSE; dkim_dstring_cat1(cur->canon_buf, *p); } else if (DKIM_ISWSP(*p)) { dkim_canon_flushblanks(cur); dkim_canon_buffer(cur, dkim_dstring_get(cur->canon_buf), dkim_dstring_len(cur->canon_buf)); dkim_dstring_blank(cur->canon_buf); cur->canon_bodystate = 1; } else { cur->canon_blankline = FALSE; dkim_dstring_cat1(cur->canon_buf, *p); cur->canon_bodystate = 3; } break; case 3: if (DKIM_ISWSP(*p)) { dkim_canon_flushblanks(cur); dkim_canon_buffer(cur, dkim_dstring_get(cur->canon_buf), dkim_dstring_len(cur->canon_buf)); dkim_dstring_blank(cur->canon_buf); cur->canon_bodystate = 1; } else if (*p == '\r') { cur->canon_bodystate = 2; } else { dkim_dstring_cat1(cur->canon_buf, *p); } break; } cur->canon_lastchar = *p; } dkim_canon_buffer(cur, NULL, 0); break; default: assert(0); /* NOTREACHED */ } } return DKIM_STAT_OK; } /* ** DKIM_CANON_CLOSEBODY -- close all body canonicalizations ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_canon_closebody(DKIM *dkim) { DKIM_CANON *cur; assert(dkim != NULL); for (cur = dkim->dkim_canonhead; cur != NULL; cur = cur->canon_next) { /* skip done hashes or header canonicalizations */ if (cur->canon_done || cur->canon_hdr) continue; /* handle unprocessed content */ if (dkim_dstring_len(cur->canon_buf) > 0) { if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF) != 0) { dkim_canon_buffer(cur, dkim_dstring_get(cur->canon_buf), dkim_dstring_len(cur->canon_buf)); dkim_canon_buffer(cur, CRLF, 2); } else { dkim_error(dkim, "CRLF at end of body missing"); return DKIM_STAT_SYNTAX; } } /* "simple" canonicalization must include at least a CRLF */ if (cur->canon_canon == DKIM_CANON_SIMPLE && cur->canon_wrote == 0) dkim_canon_buffer(cur, CRLF, 2); dkim_canon_buffer(cur, NULL, 0); /* finalize */ switch (cur->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { int alg; u_int diglen; struct dkim_sha *sha; sha = (struct dkim_sha *) cur->canon_hash; if (cur->canon_hashtype == DKIM_HASHTYPE_SHA1) alg = GNUTLS_DIG_SHA1; else alg = GNUTLS_DIG_SHA256; diglen = gnutls_hash_get_len(alg); sha->sha_out = DKIM_MALLOC(dkim, diglen); if (sha->sha_out == NULL) { dkim_error(dkim, "unable to allocate %u bytes", diglen); return DKIM_STAT_NORESOURCE; } gnutls_hash_output(sha->sha_hd, sha->sha_out); sha->sha_outlen = diglen; break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) cur->canon_hash; SHA1_Final(sha1->sha1_out, &sha1->sha1_ctx); if (sha1->sha1_tmpbio != NULL) (void) BIO_flush(sha1->sha1_tmpbio); break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) cur->canon_hash; SHA256_Final(sha256->sha256_out, &sha256->sha256_ctx); if (sha256->sha256_tmpbio != NULL) (void) BIO_flush(sha256->sha256_tmpbio); break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); /* NOTREACHED */ } cur->canon_done = TRUE; } return DKIM_STAT_OK; } /* ** DKIM_CANON_GETFINAL -- retrieve final digest ** ** Parameters: ** canon -- DKIM_CANON handle ** digest -- pointer to the digest (returned) ** dlen -- digest length (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_canon_getfinal(DKIM_CANON *canon, u_char **digest, size_t *dlen) { assert(canon != NULL); assert(digest != NULL); assert(dlen != NULL); if (!canon->canon_done) return DKIM_STAT_INVALID; switch (canon->canon_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { struct dkim_sha *sha; sha = (struct dkim_sha *) canon->canon_hash; *digest = sha->sha_out; *dlen = sha->sha_outlen; return DKIM_STAT_OK; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) canon->canon_hash; *digest = sha1->sha1_out; *dlen = sizeof sha1->sha1_out; return DKIM_STAT_OK; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) canon->canon_hash; *digest = sha256->sha256_out; *dlen = sizeof sha256->sha256_out; return DKIM_STAT_OK; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); /* NOTREACHED */ return DKIM_STAT_INTERNAL; } } /* ** DKIM_CANON_GETHASHES -- retrieve hashes ** ** Parameters: ** sig -- signature from which to get completed hashes ** hh -- pointer to header hash buffer (returned) ** hhlen -- bytes used at hh (returned) ** bh -- pointer to body hash buffer (returned) ** bhlen -- bytes used at bh (returned) ** ** Return value: ** DKIM_STAT_OK -- successful completion ** DKIM_STAT_INVALID -- hashing hasn't been completed */ DKIM_STAT dkim_canon_gethashes(DKIM_SIGINFO *sig, void **hh, size_t *hhlen, void **bh, size_t *bhlen) { DKIM_STAT status; struct dkim_canon *hdc; struct dkim_canon *bdc; u_char *hd; u_char *bd; size_t hdlen; size_t bdlen; hdc = sig->sig_hdrcanon; bdc = sig->sig_bodycanon; status = dkim_canon_getfinal(hdc, &hd, &hdlen); if (status != DKIM_STAT_OK) return status; status = dkim_canon_getfinal(bdc, &bd, &bdlen); if (status != DKIM_STAT_OK) return status; *hh = hd; *hhlen = hdlen; *bh = bd; *bhlen = bdlen; return DKIM_STAT_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-canon.h000066400000000000000000000032241337314105200231440ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_CANON_H_ #define _DKIM_CANON_H_ #include "build-config.h" /* system includes */ #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ /* libopendkim includes */ #include "dkim.h" #define DKIM_HASHBUFSIZE 4096 /* prototypes */ extern DKIM_STAT dkim_add_canon __P((DKIM *, _Bool, dkim_canon_t, int, u_char *, struct dkim_header *, ssize_t length, DKIM_CANON **)); extern DKIM_STAT dkim_canon_bodychunk __P((DKIM *, u_char *, size_t)); extern void dkim_canon_cleanup __P((DKIM *)); extern DKIM_STAT dkim_canon_closebody __P((DKIM *)); extern DKIM_STAT dkim_canon_getfinal __P((DKIM_CANON *, u_char **, size_t *)); extern DKIM_STAT dkim_canon_gethashes __P((DKIM_SIGINFO *, void **, size_t *, void **, size_t *)); extern DKIM_STAT dkim_canon_header_string __P((struct dkim_dstring *, dkim_canon_t, unsigned char *, size_t, _Bool)); extern DKIM_STAT dkim_canon_init __P((DKIM *, _Bool, _Bool)); extern u_long dkim_canon_minbody __P((DKIM *)); extern DKIM_STAT dkim_canon_runheaders __P((DKIM *)); extern int dkim_canon_selecthdrs __P((DKIM *, u_char *, struct dkim_header **, int)); extern DKIM_STAT dkim_canon_signature __P((DKIM *, struct dkim_header *)); #endif /* ! _DKIM_CANON_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-dns.c000066400000000000000000000142231337314105200226260ustar00rootroot00000000000000/* ** Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. ** */ /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* ! REENTRANT */ /* system includes */ #include #include #include #include #include #include #include #include #include #include /* libopendkim includes */ #include "dkim.h" #include "dkim-dns.h" /* OpenDKIM includes */ #include "build-config.h" /* macros, limits, etc. */ #ifndef MAXPACKET # define MAXPACKET 8192 #endif /* ! MAXPACKET */ /* ** Standard UNIX resolver stub functions */ struct dkim_res_qh { int rq_error; int rq_dnssec; size_t rq_buflen; }; /* ** DKIM_RES_INIT -- initialize the resolver ** ** Parameters: ** srv -- service handle (returned) ** ** Return value ** 0 on success, !0 on failure */ int dkim_res_init(void **srv) { #ifdef HAVE_RES_NINIT struct __res_state *res; res = malloc(sizeof(struct __res_state)); if (res == NULL) return -1; memset(res, '\0', sizeof(struct __res_state)); if (res_ninit(res) != 0) { free(res); return -1; } #ifdef RES_USE_DNSSEC res->options |= RES_USE_DNSSEC; #endif *srv = res; return 0; #else /* HAVE_RES_NINIT */ if (res_init() == 0) { #ifdef RES_USE_DNSSEC _res.options |= RES_USE_DNSSEC; #endif *srv = (void *) 0x01; return 0; } else { return -1; } #endif /* HAVE_RES_NINIT */ } /* ** DKIM_RES_CLOSE -- shut down the resolver ** ** Parameters: ** srv -- service handle ** ** Return value: ** None. */ void dkim_res_close(void *srv) { #ifdef HAVE_RES_NINIT struct __res_state *res; res = srv; if (res != NULL) { res_nclose(res); free(res); } #endif /* HAVE_RES_NINIT */ } /* ** DKIM_RES_CANCEL -- cancel a pending resolver query ** ** Parameters: ** srv -- query service handle (ignored) ** qh -- query handle (ignored) ** ** Return value: ** 0 on success, !0 on error ** ** Notes: ** The standard UNIX resolver is synchronous, so in theory this can ** never get called. We have not yet got any use cases for one thread ** canceling another thread's pending queries, so for now just return 0. */ int dkim_res_cancel(void *srv, void *qh) { if (qh != NULL) free(qh); return 0; } /* ** DKIM_RES_QUERY -- initiate a DNS query ** ** Parameters: ** srv -- service handle (ignored) ** type -- RR type to query ** query -- the question to ask ** buf -- where to write the answer ** buflen -- bytes at "buf" ** qh -- query handle, used with dkim_res_waitreply ** ** Return value: ** 0 on success, -1 on error ** ** Notes: ** This is a stub for the stock UNIX resolver (res_) functions, which ** are synchronous so no handle needs to be created, so "qh" is set to ** "buf". "buf" is actually populated before this returns (unless ** there's an error). */ int dkim_res_query(void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh) { int ret; struct dkim_res_qh *rq; #ifdef HAVE_RES_NINIT struct __res_state *statp; #endif /* HAVE_RES_NINIT */ HEADER *hdr; #ifdef HAVE_RES_NINIT statp = srv; ret = res_nquery(statp, (char *) query, C_IN, type, buf, buflen); #else /* HAVE_RES_NINIT */ ret = res_query((char *) query, C_IN, type, buf, buflen); #endif /* HAVE_RES_NINIT */ if (ret == -1) return DKIM_DNS_ERROR; rq = (struct dkim_res_qh *) malloc(sizeof *rq); if (rq == NULL) return DKIM_DNS_ERROR; hdr = (HEADER *) buf; if (hdr->ad) rq->rq_dnssec = DKIM_DNSSEC_SECURE; else rq->rq_dnssec = DKIM_DNSSEC_INSECURE; if (ret == -1) { rq->rq_error = errno; rq->rq_buflen = 0; } else { rq->rq_error = 0; rq->rq_buflen = (size_t) ret; } *qh = (void *) rq; return DKIM_DNS_SUCCESS; } /* ** DKIM_RES_WAITREPLY -- wait for a reply to a pending query ** ** Parameters: ** srv -- service handle ** qh -- query handle ** to -- timeout ** bytes -- number of bytes in the reply (returned) ** error -- error code (returned) ** ** Return value: ** A DKIM_DNS_* code. ** ** Notes: ** Since the stock UNIX resolver is synchronous, the reply was completed ** before dkim_res_query() returned, and thus this is almost a no-op. */ int dkim_res_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec) { struct dkim_res_qh *rq; assert(qh != NULL); rq = qh; if (bytes != NULL) *bytes = rq->rq_buflen; if (error != NULL) *error = rq->rq_error; if (dnssec != NULL) *dnssec = rq->rq_dnssec; return DKIM_DNS_SUCCESS; } /* ** DKIM_RES_SETNS -- set nameserver list ** ** Parameters: ** srv -- service handle ** nslist -- nameserver list, as a string ** ** Return value: ** DKIM_DNS_SUCCESS -- success ** DKIM_DNS_ERROR -- error */ int dkim_res_nslist(void *srv, const char *nslist) { #ifdef HAVE_RES_SETSERVERS int nscount = 0; char *tmp; char *ns; char *last = NULL; struct sockaddr_in in; # ifdef AF_INET6 struct sockaddr_in6 in6; # endif /* AF_INET6 */ struct state *res; res_sockaddr_union nses[MAXNS]; assert(srv != NULL); assert(nslist != NULL); memset(nses, '\0', sizeof nses); tmp = strdup(nslist); if (tmp == NULL) return DKIM_DNS_ERROR; for (ns = strtok_r(tmp, ",", &last); ns != NULL && nscount < MAXNS; ns = strtok_r(NULL, ",", &last) { memset(&in, '\0', sizeof in); # ifdef AF_INET6 memset(&in6, '\0', sizeof in6); # endif /* AF_INET6 */ if (inet_pton(AF_INET, ns, (struct in_addr *) &in.sin_addr, sizeof in.sin_addr) == 1) { in.sin_family= AF_INET; in.sin_port = htons(DNSPORT); memcpy(&nses[nscount].sin, &in, sizeof nses[nscount].sin); nscount++; } # ifdef AF_INET6 else if (inet_pton(AF_INET6, ns, (struct in6_addr *) &in6.sin6_addr, sizeof in6.sin6_addr) == 1) { in6.sin6_family= AF_INET6; in6.sin6_port = htons(DNSPORT); memcpy(&nses[nscount].sin6, &in6, sizeof nses[nscount].sin6); nscount++; } # endif /* AF_INET6 */ else { free(tmp); return DKIM_DNS_ERROR; } } res = srv; res_setservers(res, nses, nscount); free(tmp); #endif /* HAVE_RES_SETSERVERS */ return DKIM_DNS_SUCCESS; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-dns.h000066400000000000000000000012401337314105200226260ustar00rootroot00000000000000/* ** Copyright (c) 2010, 2012, The Trusted Domain Project. All rights reserved. ** */ #ifndef _DKIM_DNS_H_ #define _DKIM_DNS_H_ /* libopendkim includes */ #include "dkim.h" /* prototypes */ extern int dkim_res_cancel __P((void *, void *)); extern void dkim_res_close __P((void *)); extern int dkim_res_init __P((void **)); extern int dkim_res_nslist __P((void *, const char *)); extern int dkim_res_query __P((void *, int, unsigned char *, unsigned char *, size_t, void **)); extern int dkim_res_waitreply __P((void *, void *, struct timeval *, size_t *, int *, int *)); #endif /* ! _DKIM_DNS_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-internal.h000066400000000000000000000074501337314105200236670ustar00rootroot00000000000000/* ** Copyright (c) 2009, 2012, 2014, 2015, 2018, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_INTERNAL_H_ #define _DKIM_INTERNAL_H_ /* libopendkim includes */ #include "dkim.h" /* the basics */ #ifndef NULL # define NULL 0 #endif /* ! NULL */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifndef MAXPATHLEN # define MAXPATHLEN 256 #endif /* ! MAXPATHLEN */ #ifndef ULONG_MAX # define ULONG_MAX 0xffffffffL #endif /* ! ULONG_MAX */ #ifndef ULLONG_MAX # define ULLONG_MAX 0xffffffffffffffffLL #endif /* ! ULLONG_MAX */ #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ #ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ! MAX */ #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* limits, macros, etc. */ #define BUFRSZ 1024 /* base temp buffer size */ #define BASE64SIZE(x) (((x + 2) / 3) * 4) /* base64 encoding growth ratio */ #define MAXADDRESS 256 /* biggest user@host we accept */ #define MAXBUFRSZ 65536 /* max temp buffer size */ #define MAXCNAMEDEPTH 3 /* max. CNAME recursion we allow */ #define MAXHEADERS 32768 /* buffer for caching headers */ #define MAXLABELS 16 /* max. labels we allow */ #define MAXTAGNAME 8 /* biggest tag name */ #define NPRINTABLE 95 /* number of printable characters */ #define DKIM_MAXCDDEPTH 5 /* maximum !cd recursion */ #define DKIM_MAXHEADER 4096 /* buffer for caching one header */ #define DKIM_MAXHOSTNAMELEN 256 /* max. FQDN we support */ /* defaults */ #define DEFERRLEN 64 /* default error string length */ #define DEFTMPDIR "/tmp" /* default temporary directory */ /* version */ #define DKIM_VERSION_KEY "DKIM1" /* current version token for keys */ #define DKIM_VERSION_SIG "1" /* current version token for sigs */ #ifdef _FFR_CONDITIONAL # define DKIM_VERSION_SIG2 "2" /* new version token for sigs */ #endif /* _FFR_CONDITIONAL */ #define DKIM_VERSION_SIGOLD "0.5" /* old version token for sigs */ /* headers */ #define DKIM_DATEHEADER "Date" /* Date: header */ #define DKIM_FROMHEADER "From" /* From: header */ #define DKIM_DATEHEADER_LEN (sizeof(DKIM_DATEHEADER) - 1) #define DKIM_FROMHEADER_LEN (sizeof(DKIM_FROMHEADER) - 1) #define DKIM_SIGNHEADER_LEN (sizeof(DKIM_SIGNHEADER) - 1) /* ** DKIM_KEY -- known key parameters */ typedef int dkim_key_t; #define DKIM_KEY_VERSION 0 /* v */ #define DKIM_KEY_GRANULARITY 1 /* g */ #define DKIM_KEY_ALGORITHM 2 /* a */ #define DKIM_KEY_NOTES 3 /* n */ #define DKIM_KEY_DATA 4 /* p */ #define DKIM_KEY_SERVICE 5 /* s */ #define DKIM_KEY_FLAGS 6 /* t */ /* ** DKIM_SETTYPE -- types of sets */ typedef int dkim_set_t; #define DKIM_SETTYPE_ANY (-1) #define DKIM_SETTYPE_SIGNATURE 0 #define DKIM_SETTYPE_KEY 1 #define DKIM_SETTYPE_SIGREPORT 2 /* ** DKIM_HASHTYPE -- types of hashes */ #define DKIM_HASHTYPE_UNKNOWN (-1) #define DKIM_HASHTYPE_SHA1 0 #define DKIM_HASHTYPE_SHA256 1 /* ** DKIM_KEYTYPE -- types of keys */ #define DKIM_KEYTYPE_UNKNOWN (-1) #define DKIM_KEYTYPE_RSA 0 #define DKIM_KEYTYPE_ED25519 1 /* ** DKIM_SET -- a set of parameters and values */ struct dkim_set; typedef struct dkim_set DKIM_SET; /* ** DKIM_PLIST -- a parameter/value pair, as a linked list */ struct dkim_plist; typedef struct dkim_plist DKIM_PLIST; /* ** DKIM_KEY -- contents of a published key record */ struct dkim_key; typedef struct dkim_key DKIM_KEY; /* ** DKIM_CANON -- canonicalization */ struct dkim_canon; typedef struct dkim_canon DKIM_CANON; /* prototypes */ extern DKIM_STAT dkim_process_set __P((DKIM *, dkim_set_t, u_char *, size_t, void *, _Bool, const char *)); extern DKIM_STAT dkim_siglist_setup __P((DKIM *)); #endif /* ! _DKIM_INTERNAL_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-keys.c000066400000000000000000000264001337314105200230150ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include "build-config.h" /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-keys.h" #include "dkim-cache.h" #include "dkim-test.h" #include "util.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* prototypes */ extern void dkim_error __P((DKIM *, const char *, ...)); /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ #ifndef T_RRSIG # define T_RRSIG 46 #endif /* ! T_RRSIG */ /* ** DKIM_GET_KEY_DNS -- retrieve a DKIM key from DNS ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** buf -- buffer into which to write the result ** buflen -- bytes available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_get_key_dns(DKIM *dkim, DKIM_SIGINFO *sig, u_char *buf, size_t buflen) { #ifdef QUERY_CACHE _Bool cached = FALSE; uint32_t ttl = 0; #endif /* QUERY_CACHE */ int status; int qdcount; int ancount; int error; int dnssec = DKIM_DNSSEC_UNKNOWN; int c; int n = 0; int rdlength = 0; int type = -1; int class = -1; size_t anslen; void *q; DKIM_LIB *lib; unsigned char *txtfound = NULL; unsigned char *p; unsigned char *cp; unsigned char *eom; unsigned char *eob; unsigned char qname[DKIM_MAXHOSTNAMELEN + 1]; unsigned char ansbuf[MAXPACKET]; struct timeval timeout; HEADER hdr; assert(dkim != NULL); assert(sig != NULL); assert(sig->sig_selector != NULL); assert(sig->sig_domain != NULL); lib = dkim->dkim_libhandle; n = snprintf((char *) qname, sizeof qname - 1, "%s.%s.%s", sig->sig_selector, DKIM_DNSKEYNAME, sig->sig_domain); if (n == -1 || n > sizeof qname - 1) { dkim_error(dkim, "key query name too large"); return DKIM_STAT_NORESOURCE; } #ifdef QUERY_CACHE /* see if we have this data already cached */ if (dkim->dkim_libhandle->dkiml_cache != NULL) { int err = 0; size_t blen = buflen; dkim->dkim_cache_queries++; status = dkim_cache_query(dkim->dkim_libhandle->dkiml_cache, qname, 0, buf, &blen, &err); if (status == 0) { dkim->dkim_cache_hits++; return DKIM_STAT_OK; } /* XXX -- do something with errors here */ } #endif /* QUERY_CACHE */ /* see if there's a simulated reply queued; if so, use it */ anslen = dkim_test_dns_get(dkim, ansbuf, sizeof ansbuf); if (anslen == -1) { anslen = sizeof ansbuf; timeout.tv_sec = dkim->dkim_timeout; timeout.tv_usec = 0; if (lib->dkiml_dns_service == NULL && lib->dkiml_dns_init != NULL && lib->dkiml_dns_init(&lib->dkiml_dns_service) != 0) { dkim_error(dkim, "cannot initialize resolver"); return DKIM_STAT_KEYFAIL; } status = lib->dkiml_dns_start(lib->dkiml_dns_service, T_TXT, qname, ansbuf, anslen, &q); if (status != 0) { dkim_error(dkim, "'%s' query failed", qname); return DKIM_STAT_KEYFAIL; } if (lib->dkiml_dns_callback == NULL) { timeout.tv_sec = dkim->dkim_timeout; timeout.tv_usec = 0; status = lib->dkiml_dns_waitreply(lib->dkiml_dns_service, q, dkim->dkim_timeout == 0 ? NULL : &timeout, &anslen, &error, &dnssec); } else { struct timeval master; struct timeval next; struct timeval *wt; (void) gettimeofday(&master, NULL); master.tv_sec += dkim->dkim_timeout; for (;;) { (void) gettimeofday(&next, NULL); next.tv_sec += lib->dkiml_callback_int; dkim_min_timeval(&master, &next, &timeout, &wt); status = lib->dkiml_dns_waitreply(lib->dkiml_dns_service, q, dkim->dkim_timeout == 0 ? NULL : &timeout, &anslen, &error, &dnssec); if (wt == &next) { if (status == DKIM_DNS_NOREPLY || status == DKIM_DNS_EXPIRED) lib->dkiml_dns_callback(dkim->dkim_user_context); else break; } else { break; } } } if (status == DKIM_DNS_EXPIRED) { (void) lib->dkiml_dns_cancel(lib->dkiml_dns_service, q); dkim_error(dkim, "'%s' query timed out", qname); return DKIM_STAT_KEYFAIL; } else if (status == DKIM_DNS_ERROR) { (void) lib->dkiml_dns_cancel(lib->dkiml_dns_service, q); dkim_error(dkim, "'%s' query failed", qname); return DKIM_STAT_KEYFAIL; } (void) lib->dkiml_dns_cancel(lib->dkiml_dns_service, q); sig->sig_dnssec_key = dnssec; } /* set up pointers */ memcpy(&hdr, ansbuf, sizeof hdr); cp = (u_char *) &ansbuf + HFIXEDSZ; eom = (u_char *) &ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) &ansbuf, eom, cp, (char *) qname, sizeof qname); if ((n = dn_skipname(cp, eom)) < 0) { dkim_error(dkim, "'%s' reply corrupt", qname); return DKIM_STAT_KEYFAIL; } cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", qname); return DKIM_STAT_KEYFAIL; } GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_TXT || class != C_IN) { dkim_error(dkim, "'%s' unexpected reply class/type (%d/%d)", qname, class, type); return DKIM_STAT_KEYFAIL; } /* if NXDOMAIN, return DKIM_STAT_NOKEY */ if (hdr.rcode == NXDOMAIN) { dkim_error(dkim, "'%s' record not found", qname); return DKIM_STAT_NOKEY; } /* if truncated, we can't do it */ if (dkim_check_dns_reply(ansbuf, anslen, C_IN, T_TXT) == 1) { dkim_error(dkim, "'%s' reply truncated", qname); return DKIM_STAT_KEYFAIL; } /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) return DKIM_STAT_NOKEY; /* ** Extract the data from the first TXT answer. */ while (--ancount >= 0 && cp < eom) { /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) &ansbuf, eom, cp, (RES_UNC_T) qname, sizeof qname)) < 0) { dkim_error(dkim, "'%s' reply corrupt", qname); return DKIM_STAT_KEYFAIL; } /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ + INT32SZ + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", qname); return DKIM_STAT_KEYFAIL; } GETSHORT(type, cp); /* TYPE */ GETSHORT(class, cp); /* CLASS */ #ifdef QUERY_CACHE /* get the TTL */ GETLONG(ttl, cp); /* TTL */ #else /* QUERY_CACHE */ /* skip the TTL */ cp += INT32SZ; /* TTL */ #endif /* QUERY_CACHE */ GETSHORT(n, cp); /* RDLENGTH */ /* skip CNAME if found; assume it was resolved */ if (type == T_CNAME) { cp += n; continue; } else if (type == T_RRSIG) { cp += n; continue; } else if (type != T_TXT) { dkim_error(dkim, "'%s' reply was unexpected type %d", qname, type); return DKIM_STAT_KEYFAIL; } if (txtfound != NULL) { dkim_error(dkim, "multiple DNS replies for '%s'", qname); return DKIM_STAT_MULTIDNSREPLY; } /* remember where this one started */ txtfound = cp; rdlength = n; /* move forward for now */ cp += n; } /* if ancount went below 0, there were no good records */ if (txtfound == NULL) { dkim_error(dkim, "'%s' reply was unresolved CNAME", qname); return DKIM_STAT_NOKEY; } /* come back to the one we found */ cp = txtfound; /* ** XXX -- maybe deal with a partial reply rather than require ** it all */ if (cp + rdlength > eom) { dkim_error(dkim, "'%s' reply corrupt", qname); return DKIM_STAT_SYNTAX; } /* extract the payload */ memset(buf, '\0', buflen); p = buf; eob = buf + buflen - 1; while (rdlength > 0 && p < eob) { c = *cp++; rdlength--; while (c > 0 && p < eob) { *p++ = *cp++; c--; rdlength--; } } #ifdef QUERY_CACHE if (!cached && buf[0] != '\0' && dkim->dkim_libhandle->dkiml_cache != NULL) { int err = 0; status = dkim_cache_insert(dkim->dkim_libhandle->dkiml_cache, qname, buf, ttl, &err); /* XXX -- do something with errors here */ } #endif /* QUERY_CACHE */ return DKIM_STAT_OK; } /* ** DKIM_GET_KEY_FILE -- retrieve a DKIM key from a text file (for testing) ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** buf -- buffer into which to write the result ** buflen -- bytes available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** The file opened is defined by the library option DKIM_OPTS_QUERYINFO ** and must be set prior to use of this function. Failing to do ** so will cause this function to return DKIM_STAT_KEYFAIL every time. ** The file should contain lines of the form: ** ** ._domainkey. key-data ** ** Case matching on the left is case-sensitive, but libopendkim already ** wraps the domain name to lowercase. */ DKIM_STAT dkim_get_key_file(DKIM *dkim, DKIM_SIGINFO *sig, u_char *buf, size_t buflen) { int n; FILE *f; u_char *p; u_char *p2; u_char *path; char name[DKIM_MAXHOSTNAMELEN + 1]; assert(dkim != NULL); assert(sig != NULL); assert(sig->sig_selector != NULL); assert(sig->sig_domain != NULL); assert(sig->sig_query == DKIM_QUERY_FILE); path = dkim->dkim_libhandle->dkiml_queryinfo; if (path[0] == '\0') { dkim_error(dkim, "query file not defined"); return DKIM_STAT_KEYFAIL; } f = fopen((char *) path, "r"); if (f == NULL) { dkim_error(dkim, "%s: fopen(): %s", path, strerror(errno)); return DKIM_STAT_KEYFAIL; } n = snprintf(name, sizeof name, "%s.%s.%s", sig->sig_selector, DKIM_DNSKEYNAME, sig->sig_domain); if (n == -1 || n > sizeof name) { dkim_error(dkim, "key query name too large"); fclose(f); return DKIM_STAT_NORESOURCE; } memset(buf, '\0', buflen); while (fgets((char *) buf, buflen, f) != NULL) { if (buf[0] == '#') continue; p2 = NULL; for (p = buf; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; break; } else if (isascii(*p) && isspace(*p)) { *p = '\0'; p2 = p + 1; } else if (p2 != NULL) { break; } } if (strcasecmp((char *) name, (char *) buf) == 0 && p2 != NULL) { memmove(buf, p2, strlen(p2) + 1); fclose(f); return DKIM_STAT_OK; } } fclose(f); return DKIM_STAT_NOKEY; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-keys.h000066400000000000000000000010641337314105200230210ustar00rootroot00000000000000/* ** Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _DKIM_KEYS_H_ #define _DKIM_KEYS_H_ /* libopendkim includes */ #include "dkim.h" /* prototypes */ extern DKIM_STAT dkim_get_key_dns __P((DKIM *, DKIM_SIGINFO *, u_char *, size_t)); extern DKIM_STAT dkim_get_key_file __P((DKIM *, DKIM_SIGINFO *, u_char *, size_t)); #endif /* ! _DKIM_KEYS_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-mailparse.c000066400000000000000000000300421337314105200240140ustar00rootroot00000000000000/* ** Copyright (c) 2005, 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012, 2014, The Trusted Domain Project. ** All rights reserved. */ /* system inludes */ #include #include #include #include #include #include /* libopendkim includes */ #include "dkim-mailparse.h" /* types */ typedef unsigned long cmap_elem_type; /* symbolic names */ #define DKIM_MAILPARSE_OK 0 /* success */ #define DKIM_MAILPARSE_ERR_PUNBALANCED 1 /* unbalanced parentheses */ #define DKIM_MAILPARSE_ERR_QUNBALANCED 2 /* unbalanced quotes */ #define DKIM_MAILPARSE_ERR_SUNBALANCED 3 /* unbalanced sq. brackets */ /* a bitmap for the "specials" character class */ #define CMAP_NBITS (sizeof(cmap_elem_type) * CHAR_BIT) #define CMAP_NELEMS ((1 + UCHAR_MAX) / CMAP_NBITS) #define CMAP_INDEX(i) ((unsigned char)(i) / CMAP_NBITS) #define CMAP_BIT(i) (1L << (unsigned char)(i) % CMAP_NBITS) #define CMAP_TST(ar, c) ((ar)[CMAP_INDEX(c)] & CMAP_BIT(c)) #define CMAP_SET(ar, c) ((ar)[CMAP_INDEX(c)] |= CMAP_BIT(c)) static unsigned char const SPECIALS[] = "<>@,;:\\\"/[]?="; #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifdef DKIM_MAILPARSE_TEST /* ** DKIM_MAIL_UNESCAPE -- remove escape characters from a string ** ** Parameters: ** s -- the string to be unescaped ** ** Return value: ** s. */ static char * dkim_mail_unescape(char *s) { char *w; char const *r, *p, *e; if (s == NULL) return NULL; r = w = s; e = s + strlen(s); while ((p = memchr(r, '\\', e - s)) != NULL) { if (p > s) { if (r != w) memmove(w, r, p - r); w += p - r; } if (p[1] == '\0') { r = p + 1; } else { *w++ = p[1]; r = p + 2; } } if (r > w) { if (e > r) { memmove(w, r, e - r); w += e - r; } *w = '\0'; } return s; } #endif /* DKIM_MAILPARSE_TEST */ /* ** DKIM_MAIL_MATCHING_PAREN -- return the location past matching opposite ** parentheses ** ** Parameters: ** s -- start of string to be processed ** e -- end of string to be processed ** open_paren -- open parenthesis character ** close_paren -- close parenthesis character ** ** Return value: ** Location of the final close parenthesis character in the string. ** For example, given "xxx((yyyy)zz)aaaa", would return the location ** of the second ")". There may be more beyond that, but at that point ** everything is balanced. */ static u_char * dkim_mail_matching_paren(u_char *s, u_char *e, int open_paren, int close_paren) { int paren = 1; for (; s < e; s++) { if (*s == close_paren) { if (--paren == 0) break; } else if (*s == open_paren) { paren++; } else if (*s == '\\') { if (s[1] != '\0') s++; } } return s; } /* ** DKIM_MAIL_FIRST_SPECIAL -- find the first "special" character ** ** Parameters: ** p -- input string ** e -- end of input string ** special_out -- pointer to the first special character found ** ** Return value: ** 0 on success, or an DKIM_MAILPARSE_ERR_* on failure. */ static int dkim_mail_first_special(u_char *p, u_char *e, u_char **special_out) { size_t i; cmap_elem_type is_special[CMAP_NELEMS] = { 0 }; u_char *at_ptr = NULL; /* set up special finder */ for (i = 0; SPECIALS[i] != '\0'; i++) CMAP_SET(is_special, SPECIALS[i]); for (; p < e && *p != '\0'; p++) { /* skip white space between tokens */ while (p < e && (*p == '(' || (isascii(*p) && isspace(*p)))) { if (*p != '(') { p++; } else { p = dkim_mail_matching_paren(p + 1, e, '(', ')'); if (*p == '\0') return DKIM_MAILPARSE_ERR_PUNBALANCED; else p++; } } if (*p == '\0') break; if (*p == '"') { p = dkim_mail_matching_paren(p + 1, e, '\0', '"'); if (*p == '\0') return DKIM_MAILPARSE_ERR_QUNBALANCED; } else if (*p == '[') { p = dkim_mail_matching_paren(p + 1, e, '\0', ']'); if (*p == '\0') return DKIM_MAILPARSE_ERR_SUNBALANCED; } else if (CMAP_TST(is_special, *p)) { if (*p == '<') { *special_out = p; return 0; } else if (*p == ':' || *p == ';' || *p == ',') { if (at_ptr != NULL) *special_out = at_ptr; else *special_out = p; return 0; } else if (*p == '@') { at_ptr = p; } } else { while (*p != '\0' && !CMAP_TST(is_special, *p) && (!isascii(*p) || !isspace((unsigned char) *p)) && *p != '(') p++; p--; } } *special_out = p; return 0; } /* ** DKIM_MAIL_TOKEN -- find the next token ** ** Parameters: ** s -- start of input string ** e -- end of input string ** type_out -- type of token (returned) ** start_out -- start of token (returned) ** end_out -- start of token (returned) ** uncommented_whitespace -- set to TRUE if uncommented whitespace is ** discovered (returned) ** ** Return value: ** 0 on success, or an DKIM_MAILPARSE_ERR_* on failure. */ static int dkim_mail_token(u_char *s, u_char *e, int *type_out, u_char **start_out, u_char **end_out, int *uncommented_whitespace) { u_char *p; int err = 0; size_t i; int token_type; cmap_elem_type is_special[CMAP_NELEMS] = { 0 }; u_char *token_start, *token_end; *start_out = NULL; *end_out = NULL; *type_out = 0; err = 0; /* set up special finder */ for (i = 0; SPECIALS[i] != '\0'; i++) CMAP_SET(is_special, SPECIALS[i]); p = s; /* skip white space between tokens */ while (p < e && (*p == '(' || (isascii((unsigned char) *p) && isspace((unsigned char) *p)))) { if (*p != '(') { *uncommented_whitespace = 1; p++; } else { p = dkim_mail_matching_paren(p + 1, e, '(', ')'); if (*p == '\0') return DKIM_MAILPARSE_ERR_PUNBALANCED; else p++; } } if (p >= e || *p == '\0') return 0; /* our new token starts here */ token_start = p; /* fill in the token contents and type */ if (*p == '"') { token_end = dkim_mail_matching_paren(p + 1, e, '\0', '"'); token_type = '"'; if (*token_end != '\0') token_end++; else err = DKIM_MAILPARSE_ERR_QUNBALANCED; } else if (*p == '[') { token_end = p = dkim_mail_matching_paren(p + 1, e, '\0', ']'); token_type = '['; if (*token_end != '\0') token_end++; else err = DKIM_MAILPARSE_ERR_SUNBALANCED; } else if (CMAP_TST(is_special, *p)) { token_end = p + 1; token_type = *p; } else { while (p < e && *p != '\0' && !CMAP_TST(is_special, *p) && (!isascii(*p) || !isspace((unsigned char) *p)) && *p != '(') p++; token_end = p; token_type = 'x'; } *start_out = token_start; *end_out = token_end; *type_out = token_type; return err; } /* ** DKIM_MAIL_PARSE -- extract the local-part and hostname from a mail ** header field, e.g. "From:" ** ** Parameters: ** line -- input line ** user_out -- pointer to "local-part" (returned) ** domain_out -- pointer to hostname (returned) ** ** Return value: ** 0 on success, or an DKIM_MAILPARSE_ERR_* on failure. ** ** Notes: ** Input string is modified. */ int dkim_mail_parse(unsigned char *line, unsigned char **user_out, unsigned char **domain_out) { int type; int ws; int err; u_char *e, *special; u_char *tok_s, *tok_e; u_char *w; *user_out = NULL; *domain_out = NULL; err = 0; w = line; e = line + strlen((char *) line); ws = 0; for (;;) { err = dkim_mail_first_special(line, e, &special); if (err != 0) return err; /* given the construct we're looking at, do the right thing */ switch (*special) { case '<': /* display name
*/ line = special + 1; for (;;) { err = dkim_mail_token(line, e, &type, &tok_s, &tok_e, &ws); if (err != 0) return err; if (type == '>' || type == '\0') { *w = '\0'; return 0; } else if (type == '@') { *w++ = '\0'; *domain_out = w; } else if (type == ',' || type == ':') { /* source route punctuation */ *user_out = NULL; *domain_out = NULL; } else { if (*user_out == NULL) *user_out = w; memmove(w, tok_s, tok_e - tok_s); w += tok_e - tok_s; } line = tok_e; } case ';': case ':': case ',': /* skip a group name or result */ line = special + 1; break; default: /* (display name) addr(display name)ess */ ws = 0; for (;;) { err = dkim_mail_token(line, e, &type, &tok_s, &tok_e, &ws); if (err != 0) return err; if (type == '\0' || type == ',' || type == ';') { *w = '\0'; break; } else if (type == '@') { *w++ = '\0'; *domain_out = w; ws = 0; } else { if (*user_out == NULL) *user_out = w; else if (type == 'x' && ws == 1) *w++ = ' '; memmove(w, tok_s, tok_e - tok_s); w += tok_e - tok_s; ws = 0; } line = tok_e; } return 0; } } } /* ** DKIM_MAIL_PARSE_MULTI -- extract the local-part and hostname from a mail ** header field that might contain multiple ** values, e.g. "To:", "Cc:" ** ** Parameters: ** line -- input line ** users_out -- array of pointers to "local-part" (returned) ** domains_out -- array of pointers to hostname (returned) ** ** Return value: ** 0 on success, or an DKIM_MAILPARSE_ERR_* on failure. ** ** Notes: ** Input string is modified. */ int dkim_mail_parse_multi(unsigned char *line, unsigned char ***users_out, unsigned char ***domains_out) { _Bool escaped = FALSE; _Bool quoted = FALSE; _Bool done = FALSE; int a = 0; int n = 0; int status; int parens = 0; char *p; char *addr; unsigned char **uout = NULL; unsigned char **dout = NULL; unsigned char *u; unsigned char *d; /* walk the input string looking for unenclosed commas */ addr = line; for (p = line; !done; p++) { if (escaped) { escaped = FALSE; continue; } switch (*p) { case '\\': escaped = TRUE; continue; case ':': quoted = !quoted; continue; case '(': parens++; continue; case ')': parens--; continue; case ',': case '\0': if (parens != 0) continue; if (*p == '\0') done = TRUE; else *p = '\0'; status = dkim_mail_parse(addr, &u, &d); if (status != 0) { if (uout != NULL) { free(uout); free(dout); } return status; } if (n == 0) { size_t newsize = 2 * sizeof(unsigned char *); uout = (unsigned char **) malloc(newsize); if (uout == NULL) return -1; dout = (unsigned char **) malloc(newsize); if (dout == NULL) { free(uout); return -1; } a = 2; } else if (n + 1 == a) { unsigned char **new; size_t newsize = a * 2 * sizeof(unsigned char *); new = (unsigned char **) realloc(uout, newsize); if (new == NULL) { free(uout); free(dout); return -1; } uout = new; new = (unsigned char **) realloc(dout, newsize); if (new == NULL) { free(uout); free(dout); return -1; } dout = new; a *= 2; } uout[n] = u; dout[n++] = d; uout[n] = '\0'; dout[n] = '\0'; addr = p + 1; break; default: break; } } *users_out = uout; *domains_out = dout; return 0; } #ifdef DKIM_MAILPARSE_TEST int main(int argc, char **argv) { int err; unsigned char **domains, **users; if (argc != 2) { fprintf(stderr, "Usage: %s mailheader\n", argv[0]); exit(64); } err = dkim_mail_parse_multi(argv[1], &users, &domains); if (err != 0) { printf("error %d\n", err); } else { int n; for (n = 0; users[n] != NULL || domains[n] != NULL; n++) { printf("user: '%s'\ndomain: '%s'\n", users[n] ? dkim_mail_unescape(users[n]) : "null", domains[n] ? dkim_mail_unescape(domains[n]) : "null"); } } return 0; } #endif /* DKIM_MAILPARSE_TEST */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-mailparse.h000066400000000000000000000014401337314105200240210ustar00rootroot00000000000000/* ** Copyright (c) 2004 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_MAILPARSE_H_ #define _DKIM_MAILPARSE_H_ #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* prototypes */ extern int dkim_mail_parse __P((unsigned char *line, unsigned char **user_out, unsigned char **domain_out)); extern int dkim_mail_parse_multi __P((unsigned char *line, unsigned char ***users_out, unsigned char ***domains_out)); #endif /* ! _DKIM_MAILPARSE_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-report.c000066400000000000000000000151471337314105200233630ustar00rootroot00000000000000/* ** Copyright (c) 2012, 2013, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include /* libopendkim includes */ #include "dkim.h" #include "dkim-report.h" #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-tables.h" #include "util.h" /* prototypes */ extern void dkim_error __P((DKIM *, const char *, ...)); /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ #ifndef T_RRSIG # define T_RRSIG 46 #endif /* ! T_RRSIG */ #ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ! MAX */ /* ** DKIM_REPINFO -- retrieve reporting information from DNS ** ** Parameters: ** dkim -- DKIM message handle ** sig -- signature information handle ** timeout -- timeout (can be NULL) ** buf -- buffer into which to place the answer ** buflen -- bytes available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_repinfo(DKIM *dkim, DKIM_SIGINFO *sig, struct timeval *timeout, unsigned char *buf, size_t buflen) { int status; int qdcount; int ancount; int class = -1; int type = -1; int error; int n; unsigned int c; #ifdef QUERY_CACHE uint32_t ttl; #endif /* QUERY_CACHE */ size_t anslen; DKIM_LIB *lib; u_char *sdomain; u_char *txtfound = NULL; void *qh; u_char *p; u_char *cp; u_char *eom; struct timeval to; HEADER hdr; u_char ansbuf[MAXPACKET]; u_char query[DKIM_MAXHOSTNAMELEN + 1]; assert(dkim != NULL); assert(sig != NULL); assert(buf != NULL); lib = dkim->dkim_libhandle; sdomain = dkim_sig_getdomain(sig); if (sdomain == NULL) return DKIM_STAT_INVALID; snprintf(query, sizeof query, "%s.%s", DKIM_REPORT_PREFIX, (char *) sdomain); /* XXX -- add QUERY_CACHE support here */ if (lib->dkiml_dns_service == NULL && lib->dkiml_dns_init != NULL && lib->dkiml_dns_init(&lib->dkiml_dns_service) != 0) return DKIM_STAT_CANTVRFY; /* send it */ anslen = sizeof ansbuf; status = lib->dkiml_dns_start(lib->dkiml_dns_service, T_TXT, query, ansbuf, anslen, &qh); if (status != DKIM_DNS_SUCCESS) return DKIM_STAT_CANTVRFY; /* wait for the reply */ to.tv_sec = dkim->dkim_timeout; to.tv_usec = 0; status = lib->dkiml_dns_waitreply(lib->dkiml_dns_service, qh, timeout == NULL ? &to : timeout, &anslen, &error, NULL); (void) lib->dkiml_dns_cancel(lib->dkiml_dns_service, qh); if (status != DKIM_DNS_SUCCESS) return DKIM_STAT_CANTVRFY; /* decode the reply */ memcpy(&hdr, ansbuf, sizeof hdr); cp = (u_char *) &ansbuf + HFIXEDSZ; eom = (u_char *) &ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) &ansbuf, eom, cp, (char *) query, sizeof query); if ((n = dn_skipname(cp, eom)) < 0) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_TXT || class != C_IN) { dkim_error(dkim, "'%s' unexpected reply type/class", query); return DKIM_STAT_CANTVRFY; } if (hdr.rcode == NXDOMAIN) { buf[0] = '\0'; return DKIM_STAT_OK; } /* if truncated, we can't do it */ if (dkim_check_dns_reply(ansbuf, anslen, C_IN, T_TXT) == 1) { dkim_error(dkim, "'%s' reply truncated", query); return DKIM_STAT_CANTVRFY; } /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) { buf[0] = '\0'; return DKIM_STAT_OK; } /* ** Extract the data from the first TXT answer. */ while (--ancount >= 0 && cp < eom) { /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) &ansbuf, eom, cp, (RES_UNC_T) query, sizeof query)) < 0) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } GETSHORT(type, cp); GETSHORT(class, cp); #ifdef QUERY_CACHE /* get the TTL */ GETLONG(ttl, cp); #else /* QUERY_CACHE */ /* skip the TTL */ cp += INT32SZ; #endif /* QUERY_CACHE */ /* skip CNAME if found; assume it was resolved */ if (type == T_CNAME) { char chost[DKIM_MAXHOSTNAMELEN + 1]; n = dn_expand((u_char *) &ansbuf, eom, cp, chost, DKIM_MAXHOSTNAMELEN); cp += n; continue; } else if (type == T_RRSIG) { /* get payload length */ if (cp + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } GETSHORT(n, cp); cp += n; continue; } else if (type != T_TXT) { dkim_error(dkim, "'%s' reply was unexpected type %d", query, type); return DKIM_STAT_CANTVRFY; } if (txtfound != NULL) { dkim_error(dkim, "multiple DNS replies for '%s'", query); return DKIM_STAT_MULTIDNSREPLY; } /* remember where this one started */ txtfound = cp; /* get payload length */ if (cp + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } GETSHORT(n, cp); /* move forward for now */ cp += n; } /* if ancount went below 0, there were no good records */ if (txtfound == NULL) { dkim_error(dkim, "'%s' reply was unresolved CNAME", query); buf[0] = '\0'; return DKIM_STAT_OK; } /* come back to the one we found */ cp = txtfound; /* get payload length */ if (cp + INT16SZ > eom) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } GETSHORT(n, cp); if (cp + n > eom) { dkim_error(dkim, "'%s' reply corrupt", query); return DKIM_STAT_CANTVRFY; } /* extract the payload */ memset(buf, '\0', buflen); p = buf; eom = buf + buflen - 1; while (n > 0 && p < eom) { c = *cp++; n--; while (c > 0 && p < eom) { *p++ = *cp++; c--; n--; } } return DKIM_STAT_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-report.h000066400000000000000000000007631337314105200233660ustar00rootroot00000000000000/* ** Copyright (c) 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _DKIM_REPORT_H_ #define _DKIM_REPORT_H_ /* system includes */ #include #include /* libopendkim includes */ #include "dkim.h" /* definitions */ #define DKIM_REPORT_PREFIX "_report._domainkey" /* prototypes */ extern DKIM_STAT dkim_repinfo __P((DKIM *, DKIM_SIGINFO *, struct timeval *, unsigned char *, size_t)); #endif /* ! _DKIM_REPORT_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-tables.c000066400000000000000000000171301337314105200233140ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, 2014, 2015, 2018, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include /* libopendkim includes */ #include "dkim-tables.h" #include "dkim-internal.h" /* lookup tables */ static struct nametable prv_keyparams[] = /* key parameters */ { { "a", DKIM_KEY_ALGORITHM }, { "n", DKIM_KEY_NOTES }, { "p", DKIM_KEY_DATA }, { "s", DKIM_KEY_SERVICE }, { "t", DKIM_KEY_FLAGS }, { "v", DKIM_KEY_VERSION }, { NULL, -1 } }; struct nametable *keyparams = prv_keyparams; static struct nametable prv_keyflags[] = /* key flags */ { { "y", DKIM_SIGFLAG_TESTKEY }, { "s", DKIM_SIGFLAG_NOSUBDOMAIN }, { NULL, -1 } }; struct nametable *keyflags = prv_keyflags; static struct nametable prv_sigparams[] = /* signature parameters */ { { "a", DKIM_PARAM_SIGNALG }, { "b", DKIM_PARAM_SIGNATURE }, { "bh", DKIM_PARAM_BODYHASH }, { "c", DKIM_PARAM_CANONALG }, { "d", DKIM_PARAM_DOMAIN }, { "h", DKIM_PARAM_HDRLIST }, { "i", DKIM_PARAM_IDENTITY }, { "l", DKIM_PARAM_BODYLENGTH }, { "q", DKIM_PARAM_QUERYMETHOD }, { "s", DKIM_PARAM_SELECTOR }, { "t", DKIM_PARAM_TIMESTAMP }, { "v", DKIM_PARAM_VERSION }, { "x", DKIM_PARAM_EXPIRATION }, { "z", DKIM_PARAM_COPIEDHDRS }, { NULL, -1 } }; struct nametable *sigparams = prv_sigparams; static struct nametable prv_algorithms[] = /* signing algorithms */ { { "rsa-sha1", DKIM_SIGN_RSASHA1 }, { "rsa-sha256", DKIM_SIGN_RSASHA256 }, { "ed25519-sha256", DKIM_SIGN_ED25519SHA256 }, { NULL, -1 }, }; struct nametable *algorithms = prv_algorithms; static struct nametable prv_canonicalizations[] = /* canonicalizations */ { { "simple", DKIM_CANON_SIMPLE }, { "relaxed", DKIM_CANON_RELAXED }, { NULL, -1 }, }; struct nametable *canonicalizations = prv_canonicalizations; static struct nametable prv_hashes[] = /* hashes */ { { "sha1", DKIM_HASHTYPE_SHA1 }, { "sha256", DKIM_HASHTYPE_SHA256 }, { NULL, -1 }, }; struct nametable *hashes = prv_hashes; static struct nametable prv_keytypes[] = /* key types */ { { "rsa", DKIM_KEYTYPE_RSA }, { "ed25519", DKIM_KEYTYPE_ED25519 }, { NULL, -1 }, }; struct nametable *keytypes = prv_keytypes; static struct nametable prv_querytypes[] = /* query types */ { { "dns", DKIM_QUERY_DNS }, { NULL, -1 }, }; struct nametable *querytypes = prv_querytypes; static struct nametable prv_results[] = /* result codes */ { { "Success", DKIM_STAT_OK }, { "Bad signature", DKIM_STAT_BADSIG }, { "No signature", DKIM_STAT_NOSIG }, { "No key", DKIM_STAT_NOKEY }, { "Unable to verify", DKIM_STAT_CANTVRFY }, { "Syntax error", DKIM_STAT_SYNTAX }, { "Resource unavailable", DKIM_STAT_NORESOURCE }, { "Internal error", DKIM_STAT_INTERNAL }, { "Revoked key", DKIM_STAT_REVOKED }, { "Invalid parameter", DKIM_STAT_INVALID }, { "Not implemented", DKIM_STAT_NOTIMPLEMENT }, { "Key retrieval failed", DKIM_STAT_KEYFAIL }, { "Reject requested", DKIM_STAT_CBREJECT }, { "Invalid result", DKIM_STAT_CBINVALID }, { "Try again later", DKIM_STAT_CBTRYAGAIN }, { "Multiple DNS replies", DKIM_STAT_MULTIDNSREPLY }, { NULL, -1 }, }; struct nametable *results = prv_results; static struct nametable prv_settypes[] = /* set types */ { { "key", DKIM_SETTYPE_KEY }, { "signature", DKIM_SETTYPE_SIGNATURE }, { "signature reporting", DKIM_SETTYPE_SIGREPORT }, { NULL, -1 }, }; struct nametable *settypes = prv_settypes; static struct nametable prv_sigerrors[] = /* signature parsing errors */ { { "no signature error", DKIM_SIGERROR_OK }, { "unsupported signature version", DKIM_SIGERROR_VERSION }, { "invalid domain coverage", DKIM_SIGERROR_DOMAIN }, { "signature expired", DKIM_SIGERROR_EXPIRED }, { "signature timestamp in the future", DKIM_SIGERROR_FUTURE }, { "signature timestamp order error", DKIM_SIGERROR_TIMESTAMPS }, { "invalid header canonicalization", DKIM_SIGERROR_INVALID_HC }, { "invalid body canonicalization", DKIM_SIGERROR_INVALID_BC }, { "signature algorithm missing", DKIM_SIGERROR_MISSING_A }, { "signature algorithm invalid", DKIM_SIGERROR_INVALID_A }, { "header list missing", DKIM_SIGERROR_MISSING_H }, { "body length value invalid", DKIM_SIGERROR_INVALID_L }, { "query method invalid", DKIM_SIGERROR_INVALID_Q }, { "query option invalid", DKIM_SIGERROR_INVALID_QO }, { "domain tag missing", DKIM_SIGERROR_MISSING_D }, { "domain tag empty", DKIM_SIGERROR_EMPTY_D }, { "selector tag missing", DKIM_SIGERROR_MISSING_S }, { "selector tag empty", DKIM_SIGERROR_EMPTY_S }, { "signature data missing", DKIM_SIGERROR_MISSING_B }, { "signature data empty", DKIM_SIGERROR_EMPTY_B }, { "signature data corrupt", DKIM_SIGERROR_CORRUPT_B }, { "key not found in DNS", DKIM_SIGERROR_NOKEY }, { "key DNS reply corrupt", DKIM_SIGERROR_DNSSYNTAX }, { "key DNS query failed", DKIM_SIGERROR_KEYFAIL }, { "body hash missing", DKIM_SIGERROR_MISSING_BH }, { "body hash empty", DKIM_SIGERROR_EMPTY_BH }, { "body hash corrupt", DKIM_SIGERROR_CORRUPT_BH }, { "signature verification failed", DKIM_SIGERROR_BADSIG }, { "unauthorized subdomain", DKIM_SIGERROR_SUBDOMAIN }, { "multiple keys found", DKIM_SIGERROR_MULTIREPLY }, { "header list tag empty", DKIM_SIGERROR_EMPTY_H }, { "header list missing required entries", DKIM_SIGERROR_INVALID_H }, { "length tag value exceeds body size", DKIM_SIGERROR_TOOLARGE_L }, { "unprotected header field", DKIM_SIGERROR_MBSFAILED }, { "unknown key version", DKIM_SIGERROR_KEYVERSION }, { "unknown key hash", DKIM_SIGERROR_KEYUNKNOWNHASH }, { "signature-key hash mismatch", DKIM_SIGERROR_KEYHASHMISMATCH }, { "not an e-mail key", DKIM_SIGERROR_NOTEMAILKEY }, { "key type missing", DKIM_SIGERROR_KEYTYPEMISSING }, { "unknown key type", DKIM_SIGERROR_KEYTYPEUNKNOWN }, { "key revoked", DKIM_SIGERROR_KEYREVOKED }, { "unable to apply public key", DKIM_SIGERROR_KEYDECODE }, { "version missing", DKIM_SIGERROR_MISSING_V }, { "version empty", DKIM_SIGERROR_EMPTY_V }, { "signing key too small", DKIM_SIGERROR_KEYTOOSMALL }, #ifdef _FFR_CONDITIONAL { "conditional signature not satisfied", DKIM_SIGERROR_CONDITIONAL }, { "too many signature indirections", DKIM_SIGERROR_CONDLOOP }, #endif /* _FFR_CONDITIONAL */ { NULL, -1 }, }; struct nametable *sigerrors = prv_sigerrors; #ifdef _FFR_CONDITIONAL static struct nametable prv_mandatory[] = /* mandatory DKIM tags */ { { "!cd", 0 }, { NULL, -1 }, }; struct nametable *mandatory = prv_mandatory; #endif /* _FFR_CONDITIONAL */ /* ===================================================================== */ /* ** DKIM_CODE_TO_NAME -- translate a mnemonic code to its name ** ** Parameters: ** tbl -- name table ** code -- code to translate ** ** Return value: ** Pointer to the name matching the provided code, or NULL if not found. */ const char * dkim_code_to_name(struct nametable *tbl, const int code) { int c; assert(tbl != NULL); for (c = 0; ; c++) { if (tbl[c].tbl_code == -1 && tbl[c].tbl_name == NULL) return NULL; if (tbl[c].tbl_code == code) return tbl[c].tbl_name; } } /* ** DKIM_NAME_TO_CODE -- translate a name to a mnemonic code ** ** Parameters: ** tbl -- name table ** name -- name to translate ** ** Return value: ** A mnemonic code matching the provided name, or -1 if not found. */ const int dkim_name_to_code(struct nametable *tbl, const char *name) { int c; assert(tbl != NULL); for (c = 0; ; c++) { if (tbl[c].tbl_code == -1 && tbl[c].tbl_name == NULL) return -1; if (strcasecmp(tbl[c].tbl_name, name) == 0) return tbl[c].tbl_code; } } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-tables.h000066400000000000000000000024521337314105200233220ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012, 2014, 2015, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_TABLES_H_ #define _DKIM_TABLES_H_ #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* structures */ struct nametable { const char * tbl_name; /* name */ const int tbl_code; /* code */ }; /* tables */ extern struct nametable *algorithms; extern struct nametable *canonicalizations; extern struct nametable *hashes; extern struct nametable *keyflags; extern struct nametable *keyparams; extern struct nametable *keytypes; extern struct nametable *querytypes; extern struct nametable *results; extern struct nametable *settypes; extern struct nametable *sigerrors; extern struct nametable *sigparams; #ifdef _FFR_CONDITIONAL extern struct nametable *mandatory; #endif /* _FFR_CONDITIONAL */ /* prototypes */ extern const char *dkim_code_to_name __P((struct nametable *tbl, const int code)); extern const int dkim_name_to_code __P((struct nametable *tbl, const char *name)); #endif /* _DKIM_TABLES_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-test.c000066400000000000000000000226151337314105200230250ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012-2014, 2018, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #ifdef USE_GNUTLS # include #else /* USE_GNUTLS */ /* openssl includes */ # include # include # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-keys.h" #include "dkim-util.h" #include "dkim-test.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* definitions */ #define TESTTTL 300 #define MAXPACKET 8192 /* prototypes from elsewhere */ extern DKIM_STAT dkim_get_key __P((DKIM *, DKIM_SIGINFO *, _Bool)); /* ** DKIM_TEST_DNS_PUT -- enqueue a DNS reply for automated testing ** ** Parameters: ** dkim -- DKIM handle ** class -- class of the reply ** type -- type of the reply ** prec -- precedence (for MX replies) ** name -- name of the reply (i.e. the "question") ** data -- content of the reply ** ** Return value: ** 0 -- success ** -1 -- failure (e.g. malloc() failed) */ int dkim_test_dns_put(DKIM *dkim, int class, int type, int prec, u_char *name, u_char *data) { struct dkim_test_dns_data *td; assert(dkim != NULL); assert(name != NULL); td = (struct dkim_test_dns_data *) DKIM_MALLOC(dkim, sizeof *td); if (td == NULL) return -1; td->dns_class = class; td->dns_type = type; td->dns_prec = prec; td->dns_query = dkim_strdup(dkim, name, 0); if (td->dns_query == NULL) { DKIM_FREE(dkim, td); return -1; } if (data != NULL) { td->dns_reply = dkim_strdup(dkim, data, 0); if (td->dns_reply == NULL) { DKIM_FREE(dkim, td->dns_query); DKIM_FREE(dkim, td); return -1; } } td->dns_next = NULL; if (dkim->dkim_dnstesth == NULL) dkim->dkim_dnstesth = td; else dkim->dkim_dnstestt->dns_next = td; dkim->dkim_dnstestt = td; return 0; } /* ** DKIM_TEST_DNS_GET -- dequeue a DNS reply for automated testing ** ** Parameters: ** dkim -- DKIM handle ** buf -- target buffer ** buflen -- bytes available at "buf" ** ** Return value: ** -1 -- nothing queued ** other -- size of the reply */ size_t dkim_test_dns_get(DKIM *dkim, u_char *buf, size_t buflen) { int n; int len; uint32_t testttl; struct dkim_test_dns_data *td; u_char *cp; u_char *p; u_char *end; u_char answer[MAXPACKET]; HEADER hdr; td = dkim->dkim_dnstesth; if (td == NULL) return -1; dkim->dkim_dnstesth = td->dns_next; /* encode the reply */ memset(&hdr, '\0', sizeof hdr); hdr.qdcount = htons(1); hdr.rcode = (td->dns_reply == NULL ? NXDOMAIN : NOERROR); hdr.ancount = (td->dns_reply == NULL ? htons(0) : htons(1)); memcpy(answer, &hdr, sizeof hdr); cp = answer + HFIXEDSZ; end = answer + sizeof answer; /* repeat the question */ n = dn_comp((char *) td->dns_query, cp, end - cp, NULL, NULL); if (n < 0) { DKIM_FREE(dkim, td); return -1; } cp += n; if (end - cp < 2 * sizeof(uint16_t)) { DKIM_FREE(dkim, td); return -1; } PUTSHORT(td->dns_type, cp); PUTSHORT(td->dns_class, cp); /* short-circuit? */ if (hdr.rcode == NXDOMAIN) { DKIM_FREE(dkim, td); memcpy(buf, answer, buflen); return cp - answer; } /* the answer starts out the same way */ n = dn_comp((char *) td->dns_query, cp, end - cp, NULL, NULL); if (n < 0) { DKIM_FREE(dkim, td); return -1; } cp += n; if (end - cp < 2 * sizeof(uint16_t) + sizeof(uint32_t)) { DKIM_FREE(dkim, td); return -1; } PUTSHORT(td->dns_type, cp); PUTSHORT(td->dns_class, cp); testttl = htonl(TESTTTL); PUTLONG(testttl, cp); switch (td->dns_type) { case T_TXT: /* figure out how many bytes we need total */ n = strlen((char *) td->dns_reply); len = n + n / 255 + 1; if (end - cp < len + sizeof(uint16_t)) { DKIM_FREE(dkim, td); return -1; } PUTSHORT(len, cp); /* write the buffer, inserting length bytes as needed */ len = 0; p = td->dns_reply; while (n > 0) { if (len == 0) { len = MIN(255, n); *cp++ = len; } *cp++ = *p++; n--; len--; } break; case T_MX: if (end - cp < sizeof(uint16_t)) { DKIM_FREE(dkim, td); return -1; } PUTSHORT(td->dns_prec, cp); n = dn_comp((char *) td->dns_reply, cp, end - cp, NULL, NULL); if (n < 0) { DKIM_FREE(dkim, td); return -1; } cp += n; break; default: DKIM_FREE(dkim, td); return -1; } DKIM_FREE(dkim, td); memcpy(buf, answer, buflen); return cp - answer; } /* ** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided ** private key ** ** Parameters: ** lib -- DKIM library handle ** selector -- selector ** domain -- domain name ** key -- private key to verify (PEM format) ** keylen -- size of private key ** dnssec -- DNSSEC result (may be NULL) ** err -- error buffer (may be NULL) ** errlen -- size of error buffer ** ** Return value: ** 1 -- keys don't match ** 0 -- keys match (or no key provided) ** -1 -- error */ int dkim_test_key(DKIM_LIB *lib, char *selector, char *domain, char *key, size_t keylen, int *dnssec, char *err, size_t errlen) { int status = 0; DKIM_STAT stat; DKIM *dkim; DKIM_SIGINFO *sig; #ifdef USE_GNUTLS gnutls_datum_t keybuf; gnutls_datum_t outkey; #else /* USE_GNUTLS */ BIO *keybuf; BIO *outkey; #endif /* USE_GNUTLS */ void *ptr; struct dkim_crypto *crypto; char buf[BUFRSZ]; assert(lib != NULL); assert(selector != NULL); assert(domain != NULL); dkim = dkim_verify(lib, (u_char *) "test", NULL, &stat); if (dkim == NULL) { if (err != NULL) strlcpy(err, dkim_getresultstr(stat), errlen); return -1; } snprintf(buf, sizeof buf, "v=1; d=%s; s=%s; h=x; b=x; a=x", domain, selector); stat = dkim_process_set(dkim, DKIM_SETTYPE_SIGNATURE, (u_char *) buf, strlen(buf), NULL, FALSE, NULL); if (stat != DKIM_STAT_OK) { strlcpy(err, "syntax error on input", errlen); (void) dkim_free(dkim); return -1; } dkim->dkim_sigcount = 1; stat = dkim_siglist_setup(dkim); if (stat != DKIM_STAT_OK) { (void) dkim_free(dkim); return -1; } sig = dkim->dkim_siglist[0]; dkim->dkim_user = dkim_strdup(dkim, (u_char *) "nobody", 0); if (dkim->dkim_user == NULL) { (void) dkim_free(dkim); return -1; } stat = dkim_get_key(dkim, sig, TRUE); if (stat != DKIM_STAT_OK) { if (err != NULL) { const char *errstr; errstr = dkim_geterror(dkim); if (errstr != NULL) { strlcpy(err, errstr, errlen); } else { strlcpy(err, dkim_getresultstr(stat), errlen); } } (void) dkim_free(dkim); return -1; } if (dnssec != NULL) *dnssec = dkim_sig_getdnssec(sig); if (key != NULL) { crypto = DKIM_MALLOC(dkim, sizeof(struct dkim_crypto)); if (crypto == NULL) { (void) dkim_free(dkim); if (err != NULL) { snprintf(err, errlen, "unable to allocate %zu byte(s)", sizeof(struct dkim_crypto)); } return -1; } memset(crypto, '\0', sizeof(struct dkim_crypto)); #ifdef USE_GNUTLS keybuf.data = key; keybuf.size = keylen; #else /* USE_GNUTLS */ keybuf = BIO_new_mem_buf(key, keylen); if (keybuf == NULL) { if (err != NULL) { strlcpy(err, "BIO_new_mem_buf() failed", errlen); } (void) dkim_free(dkim); return -1; } #endif /* USE_GNUTLS */ sig->sig_signature = (void *) crypto; sig->sig_keytype = DKIM_KEYTYPE_RSA; #ifdef USE_GNUTLS if (err != NULL) strlcpy(err, "function not implemented", errlen); (void) dkim_free(dkim); return -1; #else /* USE_GNUTLS */ crypto->crypto_pkey = PEM_read_bio_PrivateKey(keybuf, NULL, NULL, NULL); if (crypto->crypto_pkey == NULL) { BIO_free(keybuf); (void) dkim_free(dkim); if (err != NULL) { strlcpy(err, "PEM_read_bio_PrivateKey() failed", errlen); } return -1; } crypto->crypto_key = EVP_PKEY_get1_RSA(crypto->crypto_pkey); if (crypto->crypto_key == NULL) { BIO_free(keybuf); (void) dkim_free(dkim); if (err != NULL) { strlcpy(err, "EVP_PKEY_get1_RSA() failed", errlen); } return -1; } crypto->crypto_keysize = RSA_size(crypto->crypto_key); crypto->crypto_pad = RSA_PKCS1_PADDING; outkey = BIO_new(BIO_s_mem()); if (outkey == NULL) { BIO_free(keybuf); (void) dkim_free(dkim); if (err != NULL) strlcpy(err, "BIO_new() failed", errlen); return -1; } status = i2d_RSA_PUBKEY_bio(outkey, crypto->crypto_key); if (status == 0) { BIO_free(keybuf); BIO_free(outkey); (void) dkim_free(dkim); if (err != NULL) { strlcpy(err, "i2d_RSA_PUBKEY_bio() failed", errlen); } return -1; } (void) BIO_get_mem_data(outkey, &ptr); if (BIO_number_written(outkey) == sig->sig_keylen) status = memcmp(ptr, sig->sig_key, sig->sig_keylen); else status = 1; if (status != 0) strlcpy(err, "keys do not match", errlen); BIO_free(keybuf); BIO_free(outkey); #endif /* USE_GNUTLS */ } (void) dkim_free(dkim); return (status == 0 ? 0 : 1); } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-test.h000066400000000000000000000007161337314105200230300ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _DKIM_TEST_H_ #define _DKIM_TEST_H_ /* libopendkim includes */ #include "dkim.h" /* prototypes */ extern size_t dkim_test_dns_get __P((DKIM *, u_char *, size_t)); extern int dkim_test_dns_put __P((DKIM *, int, int, int, u_char *, u_char *)); #endif /* ! _DKIM_TEST_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-types.h000066400000000000000000000243041337314105200232140ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, 2018, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_TYPES_H_ #define _DKIM_TYPES_H_ #include "build-config.h" /* system includes */ #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #ifdef USE_TRE # ifdef TRE_PRE_080 # include # else /* TRE_PRE_080 */ # include # endif /* TRE_PRE_080 */ #else /* USE_TRE */ # include #endif /* USE_TRE */ #ifdef USE_GNUTLS # include # include # include #else /* USE_GNUTLS */ /* OpenSSL includes */ # include # include # include # include # include #endif /* USE_GNUTLS */ #ifdef QUERY_CACHE /* libdb includes */ # include #endif /* QUERY_CACHE */ /* libopendkim includes */ #include "dkim.h" #include "dkim-internal.h" /* struct dkim_qmethod -- signature query method */ struct dkim_qmethod { char * qm_type; char * qm_options; struct dkim_qmethod * qm_next; }; /* struct dkim_xtag -- signature extension tag */ struct dkim_xtag { char * xt_tag; char * xt_value; struct dkim_xtag * xt_next; }; /* struct dkim_queryinfo -- DNS query information */ struct dkim_queryinfo { int dq_type; const char dq_name[DKIM_MAXHOSTNAMELEN + 1]; }; /* struct dkim_dstring -- a dynamically-sized string */ struct dkim_dstring { int ds_alloc; int ds_max; int ds_len; DKIM * ds_dkim; unsigned char * ds_buf; }; /* struct dkim_header -- an RFC2822 header of some kind */ struct dkim_header { int hdr_flags; size_t hdr_textlen; size_t hdr_namelen; u_char * hdr_text; u_char * hdr_colon; struct dkim_header * hdr_next; }; /* hdr_flags bits */ #define DKIM_HDR_SIGNED 0x01 /* struct dkim_plist -- a parameter/value pair */ struct dkim_plist { u_char * plist_param; u_char * plist_value; struct dkim_plist * plist_next; }; /* struct dkim_set -- a set of parameter/value pairs */ struct dkim_set { _Bool set_bad; #ifdef _FFR_CONDITIONAL u_int set_minv; #endif /* _FFR_CONDITIONAL */ dkim_set_t set_type; u_char * set_data; const char * set_name; void * set_udata; struct dkim_plist * set_plist[NPRINTABLE]; struct dkim_set * set_next; }; /* struct dkim_siginfo -- signature information for use by the caller */ struct dkim_siginfo { int sig_dnssec_key; u_int sig_flags; u_int sig_error; u_int sig_bh; u_int sig_version; u_int sig_hashtype; u_int sig_keytype; u_int sig_keybits; size_t sig_siglen; size_t sig_keylen; size_t sig_b64keylen; dkim_query_t sig_query; dkim_alg_t sig_signalg; dkim_canon_t sig_hdrcanonalg; dkim_canon_t sig_bodycanonalg; uint64_t sig_timestamp; u_char * sig_domain; u_char * sig_selector; u_char * sig_sig; u_char * sig_key; u_char * sig_b64key; void * sig_context; void * sig_signature; struct dkim_canon * sig_hdrcanon; struct dkim_canon * sig_bodycanon; struct dkim_set * sig_taglist; struct dkim_set * sig_keytaglist; struct dkim_dstring * sig_sslerrbuf; }; #ifdef USE_GNUTLS /* struct dkim_sha -- stuff needed to do a sha hash */ struct dkim_sha { int sha_tmpfd; u_int sha_outlen; gnutls_hash_hd_t sha_hd; u_char * sha_out; }; #else /* USE_GNUTLS */ /* struct dkim_sha1 -- stuff needed to do a sha1 hash */ struct dkim_sha1 { int sha1_tmpfd; BIO * sha1_tmpbio; SHA_CTX sha1_ctx; u_char sha1_out[SHA_DIGEST_LENGTH]; }; # ifdef HAVE_SHA256 /* struct dkim_sha256 -- stuff needed to do a sha256 hash */ struct dkim_sha256 { int sha256_tmpfd; BIO * sha256_tmpbio; SHA256_CTX sha256_ctx; u_char sha256_out[SHA256_DIGEST_LENGTH]; }; # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ /* struct dkim_canon -- a canonicalization status handle */ struct dkim_canon { _Bool canon_done; _Bool canon_hdr; _Bool canon_blankline; int canon_lastchar; int canon_bodystate; u_int canon_hashtype; u_int canon_blanks; size_t canon_hashbuflen; size_t canon_hashbufsize; ssize_t canon_remain; ssize_t canon_wrote; ssize_t canon_length; dkim_canon_t canon_canon; u_char * canon_hashbuf; u_char * canon_hdrlist; void * canon_hash; struct dkim_dstring * canon_buf; struct dkim_header * canon_sigheader; struct dkim_canon * canon_next; }; /* struct dkim_crypto -- stuff needed to do RSA sign/verify */ struct dkim_crypto { #ifdef USE_GNUTLS size_t crypto_rsaoutlen; unsigned int crypto_keysize; gnutls_x509_privkey_t crypto_key; gnutls_privkey_t crypto_privkey; gnutls_pubkey_t crypto_pubkey; gnutls_datum_t crypto_sig; gnutls_datum_t crypto_digest; gnutls_datum_t crypto_rsaout; gnutls_datum_t crypto_keydata; #else /* USE_GNUTLS */ u_char crypto_pad; int crypto_keysize; size_t crypto_inlen; size_t crypto_outlen; EVP_PKEY * crypto_pkey; void * crypto_key; BIO * crypto_keydata; u_char * crypto_in; u_char * crypto_out; #endif /* USE_GNUTLS */ }; /* struct dkim_test_dns_data -- simulated DNS replies */ struct dkim_test_dns_data { int dns_class; int dns_type; int dns_prec; u_char * dns_query; u_char * dns_reply; struct dkim_test_dns_data * dns_next; }; /* struct dkim_unbound_cb_data -- libunbound callback data */ struct dkim_unbound_cb_data { int ubd_done; int ubd_rcode; int ubd_id; int ubd_type; u_int ubd_result; DKIM_STAT ubd_stat; size_t ubd_buflen; u_char * ubd_buf; const char * ubd_jobid; }; /* struct dkim -- a complete DKIM transaction context */ struct dkim { _Bool dkim_partial; _Bool dkim_bodydone; _Bool dkim_subdomain; _Bool dkim_skipbody; #ifdef _FFR_RESIGN _Bool dkim_hdrbind; #endif /* _FFR_RESIGN */ _Bool dkim_eoh_reentry; int dkim_mode; int dkim_state; int dkim_chunkstate; int dkim_chunksm; int dkim_chunkcrlf; int dkim_timeout; int dkim_presult; int dkim_hdrcnt; int dkim_minsiglen; #ifdef _FFR_CONDITIONAL int dkim_cddepth; #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_RESIGN u_int dkim_refcnt; #endif /* _FFR_RESIGN */ #ifdef QUERY_CACHE u_int dkim_cache_queries; u_int dkim_cache_hits; #endif /* QUERY_CACHE */ u_int dkim_version; u_int dkim_sigcount; size_t dkim_margin; size_t dkim_b64siglen; size_t dkim_keylen; size_t dkim_errlen; uint64_t dkim_timestamp; struct dkim_qmethod * dkim_querymethods; dkim_canon_t dkim_hdrcanonalg; dkim_canon_t dkim_bodycanonalg; dkim_alg_t dkim_signalg; #ifdef _FFR_ATPS _Bool dkim_atps; #endif /* _FFR_ATPS */ ssize_t dkim_bodylen; ssize_t dkim_signlen; const u_char * dkim_id; u_char * dkim_domain; u_char * dkim_user; u_char * dkim_selector; u_char * dkim_b64key; u_char * dkim_b64sig; u_char * dkim_key; u_char * dkim_reportaddr; u_char * dkim_sender; u_char * dkim_signer; #ifdef _FFR_CONDITIONAL u_char * dkim_conditional; #endif /* _FFR_CONDITIONAL */ u_char * dkim_error; u_char * dkim_hdrlist; u_char * dkim_zdecode; u_char * dkim_tmpdir; DKIM_SIGINFO * dkim_signature; void * dkim_keydata; void * dkim_closure; const void * dkim_user_context; #ifdef _FFR_RESIGN DKIM * dkim_resign; #endif /* _FFR_RESIGN */ struct dkim_xtag * dkim_xtags; struct dkim_siginfo ** dkim_siglist; struct dkim_set * dkim_sethead; struct dkim_set * dkim_settail; struct dkim_set * dkim_sigset; struct dkim_header * dkim_hhead; struct dkim_header * dkim_htail; struct dkim_header * dkim_senderhdr; struct dkim_canon * dkim_canonhead; struct dkim_canon * dkim_canontail; struct dkim_dstring * dkim_hdrbuf; struct dkim_dstring * dkim_canonbuf; struct dkim_dstring * dkim_sslerrbuf; struct dkim_test_dns_data * dkim_dnstesth; struct dkim_test_dns_data * dkim_dnstestt; regex_t * dkim_hdrre; DKIM_LIB * dkim_libhandle; }; /* struct dkim_lib -- a DKIM library context */ struct dkim_lib { _Bool dkiml_signre; _Bool dkiml_skipre; _Bool dkiml_dnsinit_done; u_int dkiml_timeout; u_int dkiml_version; u_int dkiml_callback_int; u_int dkiml_flsize; u_int dkiml_minkeybits; uint32_t dkiml_flags; uint64_t dkiml_fixedtime; uint64_t dkiml_sigttl; uint64_t dkiml_clockdrift; dkim_query_t dkiml_querymethod; u_int * dkiml_flist; void * (*dkiml_malloc) (void *closure, size_t nbytes); void (*dkiml_free) (void *closure, void *p); u_char ** dkiml_requiredhdrs; u_char ** dkiml_oversignhdrs; u_char ** dkiml_mbs; #ifdef QUERY_CACHE DB * dkiml_cache; #endif /* QUERY_CACHE */ regex_t dkiml_hdrre; regex_t dkiml_skiphdrre; DKIM_CBSTAT (*dkiml_key_lookup) (DKIM *dkim, DKIM_SIGINFO *sig, u_char *buf, size_t buflen); void * (*dkiml_sig_handle) (void *closure); void (*dkiml_sig_handle_free) (void *closure, void *user); void (*dkiml_sig_tagvalues) (void *user, dkim_param_t pcode, const u_char *param, const u_char *value); DKIM_CBSTAT (*dkiml_prescreen) (DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs); DKIM_CBSTAT (*dkiml_final) (DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs); void (*dkiml_dns_callback) (const void *context); void *dkiml_dns_service; int (*dkiml_dns_init) (void **srv); void (*dkiml_dns_close) (void *srv); int (*dkiml_dns_start) (void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh); int (*dkiml_dns_cancel) (void *srv, void *qh); int (*dkiml_dns_setns) (void *srv, const char *ns); int (*dkiml_dns_config) (void *srv, const char *conf); int (*dkiml_dns_trustanchor) (void *srv, const char *ta); int (*dkiml_dns_waitreply) (void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec); u_char dkiml_tmpdir[MAXPATHLEN + 1]; u_char dkiml_queryinfo[MAXPATHLEN + 1]; }; #endif /* _DKIM_TYPES_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-util.c000066400000000000000000000262371337314105200230270ustar00rootroot00000000000000/* ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, 2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #include #include #include /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-util.h" /* prototypes */ extern void dkim_error __P((DKIM *, const char *, ...)); /* ** DKIM_MALLOC -- allocate memory ** ** Parameters: ** libhandle -- DKIM library context in which this is performed ** closure -- opaque closure handle for the allocation ** nbytes -- number of bytes desired ** ** Return value: ** Pointer to allocated memory, or NULL on failure. */ void * dkim_malloc(DKIM_LIB *libhandle, void *closure, size_t nbytes) { assert(libhandle != NULL); if (libhandle->dkiml_malloc == NULL) return malloc(nbytes); else return libhandle->dkiml_malloc(closure, nbytes); } /* ** DKIM_MFREE -- release memory ** ** Parameters: ** dkim -- DKIM context in which this is performed ** closure -- opaque closure handle for the allocation ** ptr -- pointer to memory to be freed ** ** Return value: ** None. */ void dkim_mfree(DKIM_LIB *libhandle, void *closure, void *ptr) { assert(libhandle != NULL); if (libhandle->dkiml_free == NULL) free(ptr); else libhandle->dkiml_free(closure, ptr); } /* ** DKIM_STRDUP -- duplicate a string ** ** Parameters: ** dkim -- DKIM handle ** str -- string to clone ** len -- bytes to copy (0 == copy to NULL byte) ** ** Return value: ** Pointer to a new copy of "str" allocated from within the appropriate ** context, or NULL on failure. */ unsigned char * dkim_strdup(DKIM *dkim, const unsigned char *str, size_t len) { unsigned char *new; assert(dkim != NULL); assert(str != NULL); if (len == 0) len = strlen((char *) str); new = dkim_malloc(dkim->dkim_libhandle, dkim->dkim_closure, len + 1); if (new != NULL) { memcpy(new, str, len); new[len] = '\0'; } else { dkim_error(dkim, "unable to allocate %d byte(s)", len + 1); } return new; } /* ** DKIM_TMPFILE -- open a temporary file ** ** Parameters: ** dkim -- DKIM handle ** fp -- descriptor (returned) ** keep -- if FALSE, unlink() the file once created ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_tmpfile(DKIM *dkim, int *fp, _Bool keep) { int fd; char *p; char path[MAXPATHLEN + 1]; assert(dkim != NULL); assert(fp != NULL); if (dkim->dkim_id != NULL) { snprintf(path, MAXPATHLEN, "%s/dkim.%s.XXXXXX", dkim->dkim_libhandle->dkiml_tmpdir, dkim->dkim_id); } else { snprintf(path, MAXPATHLEN, "%s/dkim.XXXXXX", dkim->dkim_libhandle->dkiml_tmpdir); } for (p = path + strlen((char *) dkim->dkim_libhandle->dkiml_tmpdir) + 1; *p != '\0'; p++) { if (*p == '/') *p = '.'; } fd = mkstemp(path); if (fd == -1) { dkim_error(dkim, "can't create temporary file at %s: %s", path, strerror(errno)); return DKIM_STAT_NORESOURCE; } *fp = fd; if (!keep) (void) unlink(path); return DKIM_STAT_OK; } /* ** DKIM_DSTRING_RESIZE -- resize a dynamic string (dstring) ** ** Parameters: ** dstr -- DKIM_DSTRING handle ** len -- number of bytes desired ** ** Return value: ** TRUE iff the resize worked (or wasn't needed) ** ** Notes: ** This will actually ensure that there are "len" bytes available. ** The caller must account for the NULL byte when requesting a ** specific size. */ static _Bool dkim_dstring_resize(struct dkim_dstring *dstr, int len) { int newsz; unsigned char *new; DKIM *dkim; DKIM_LIB *lib; assert(dstr != NULL); assert(len > 0); if (dstr->ds_alloc >= len) return TRUE; dkim = dstr->ds_dkim; lib = dkim->dkim_libhandle; /* must resize */ for (newsz = dstr->ds_alloc * 2; newsz < len; newsz *= 2) { /* impose ds_max limit, if specified */ if (dstr->ds_max > 0 && newsz > dstr->ds_max) { if (len <= dstr->ds_max) { newsz = len; break; } dkim_error(dkim, "maximum string size exceeded"); return FALSE; } /* check for overflow */ if (newsz > INT_MAX / 2) { /* next iteration will overflow "newsz" */ dkim_error(dkim, "internal string limit reached"); return FALSE; } } new = dkim_malloc(lib, dkim->dkim_closure, newsz); if (new == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", newsz); return FALSE; } memcpy(new, dstr->ds_buf, dstr->ds_alloc); dkim_mfree(lib, dkim->dkim_closure, dstr->ds_buf); dstr->ds_alloc = newsz; dstr->ds_buf = new; return TRUE; } /* ** DKIM_DSTRING_NEW -- make a new dstring ** ** Parameters: ** dkim -- DKIM handle ** len -- initial number of bytes ** maxlen -- maximum allowed length, including the NULL byte ** (0 == unbounded) ** ** Return value: ** A DKIM_DSTRING handle, or NULL on failure. */ struct dkim_dstring * dkim_dstring_new(DKIM *dkim, int len, int maxlen) { struct dkim_dstring *new; DKIM_LIB *lib; assert(dkim != NULL); /* fail on invalid parameters */ if ((maxlen > 0 && len > maxlen) || len < 0) return NULL; lib = dkim->dkim_libhandle; if (len < BUFRSZ) len = BUFRSZ; new = dkim_malloc(lib, dkim->dkim_closure, sizeof(struct dkim_dstring)); if (new == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_dstring)); return NULL; } new->ds_buf = dkim_malloc(lib, dkim->dkim_closure, len); if (new->ds_buf == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_dstring)); dkim_mfree(lib, dkim->dkim_closure, new); return NULL; } memset(new->ds_buf, '\0', len); new->ds_alloc = len; new->ds_len = 0; new->ds_max = maxlen; new->ds_dkim = dkim; return new; } /* ** DKIM_DSTRING_FREE -- destroy an existing dstring ** ** Parameters: ** dstr -- DKIM_DSTRING handle to be destroyed ** ** Return value: ** None. */ void dkim_dstring_free(struct dkim_dstring *dstr) { DKIM_LIB *lib; DKIM *dkim; assert(dstr != NULL); dkim = dstr->ds_dkim; lib = dkim->dkim_libhandle; dkim_mfree(lib, dkim->dkim_closure, dstr->ds_buf); dkim_mfree(lib, dkim->dkim_closure, dstr); } /* ** DKIM_DSTRING_COPY -- copy data into a dstring ** ** Parameters: ** dstr -- DKIM_DSTRING handle to update ** str -- input string ** ** Return value: ** TRUE iff the copy succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkim_dstring_copy(struct dkim_dstring *dstr, unsigned char *str) { int len; assert(dstr != NULL); assert(str != NULL); len = strlen((char *) str); /* too big? */ if (dstr->ds_max > 0 && len >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= len) { /* nope; try to resize */ if (!dkim_dstring_resize(dstr, len + 1)) return FALSE; } /* copy */ memcpy(dstr->ds_buf, str, len + 1); dstr->ds_len = len; return TRUE; } /* ** DKIM_DSTRING_CAT -- append data onto a dstring ** ** Parameters: ** dstr -- DKIM_DSTRING handle to update ** str -- input string ** ** Return value: ** TRUE iff the update succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkim_dstring_cat(struct dkim_dstring *dstr, unsigned char *str) { size_t len; size_t needed; assert(dstr != NULL); assert(str != NULL); len = strlen((char *) str); needed = dstr->ds_len + len; /* too big? */ if (dstr->ds_max > 0 && needed >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= needed) { /* nope; try to resize */ if (!dkim_dstring_resize(dstr, needed + 1)) return FALSE; } /* append */ memcpy(dstr->ds_buf + dstr->ds_len, str, len + 1); dstr->ds_len += len; return TRUE; } /* ** DKIM_DSTRING_CAT1 -- append one byte onto a dstring ** ** Parameters: ** dstr -- DKIM_DSTRING handle to update ** c -- input character ** ** Return value: ** TRUE iff the update succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkim_dstring_cat1(struct dkim_dstring *dstr, int c) { int len; assert(dstr != NULL); len = dstr->ds_len + 1; /* too big? */ if (dstr->ds_max > 0 && len >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= len) { /* nope; try to resize */ if (!dkim_dstring_resize(dstr, len + 1)) return FALSE; } /* append */ dstr->ds_buf[dstr->ds_len++] = c; dstr->ds_buf[dstr->ds_len] = '\0'; return TRUE; } /* ** DKIM_DSTRING_CATN -- append 'n' bytes onto a dstring ** ** Parameters: ** dstr -- DKIM_DSTRING handle to update ** str -- input string ** nbytes -- number of bytes to append ** ** Return value: ** TRUE iff the update succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkim_dstring_catn(struct dkim_dstring *dstr, unsigned char *str, size_t nbytes) { size_t needed; assert(dstr != NULL); assert(str != NULL); needed = dstr->ds_len + nbytes; /* too big? */ if (dstr->ds_max > 0 && needed >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= needed) { /* nope; try to resize */ if (!dkim_dstring_resize(dstr, needed + 1)) return FALSE; } /* append */ memcpy(dstr->ds_buf + dstr->ds_len, str, nbytes); dstr->ds_len += nbytes; dstr->ds_buf[dstr->ds_len] = '\0'; return TRUE; } /* ** DKIM_DSTRING_GET -- retrieve data in a dstring ** ** Parameters: ** dstr -- DKIM_STRING handle whose string should be retrieved ** ** Return value: ** Pointer to the NULL-terminated contents of "dstr". */ unsigned char * dkim_dstring_get(struct dkim_dstring *dstr) { assert(dstr != NULL); return dstr->ds_buf; } /* ** DKIM_DSTRING_LEN -- retrieve length of data in a dstring ** ** Parameters: ** dstr -- DKIM_STRING handle whose string should be retrieved ** ** Return value: ** Number of bytes in a dstring. */ int dkim_dstring_len(struct dkim_dstring *dstr) { assert(dstr != NULL); return dstr->ds_len; } /* ** DKIM_DSTRING_BLANK -- clear out the contents of a dstring ** ** Parameters: ** dstr -- DKIM_STRING handle whose string should be cleared ** ** Return value: ** None. */ void dkim_dstring_blank(struct dkim_dstring *dstr) { assert(dstr != NULL); dstr->ds_len = 0; dstr->ds_buf[0] = '\0'; } /* ** DKIM_DSTRING_PRINTF -- write variable length formatted output to a dstring ** ** Parameters: ** dstr -- DKIM_STRING handle to be updated ** fmt -- format ** ... -- variable arguments ** ** Return value: ** New size, or -1 on error. */ size_t dkim_dstring_printf(struct dkim_dstring *dstr, char *fmt, ...) { size_t len; size_t rem; va_list ap; va_list ap2; assert(dstr != NULL); assert(fmt != NULL); va_start(ap, fmt); va_copy(ap2, ap); rem = dstr->ds_alloc - dstr->ds_len; len = vsnprintf((char *) dstr->ds_buf + dstr->ds_len, rem, fmt, ap); va_end(ap); if (len > rem) { if (!dkim_dstring_resize(dstr, dstr->ds_len + len + 1)) { va_end(ap2); return (size_t) -1; } rem = dstr->ds_alloc - dstr->ds_len; len = vsnprintf((char *) dstr->ds_buf + dstr->ds_len, rem, fmt, ap2); } va_end(ap2); dstr->ds_len += len; return dstr->ds_len; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim-util.h000066400000000000000000000031641337314105200230260ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _DKIM_UTIL_H_ #define _DKIM_UTIL_H_ #include "build-config.h" /* system includes */ #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ /* libopendkim includes */ #include "dkim.h" /* macros */ #define DKIM_MALLOC(x,y) dkim_malloc((x)->dkim_libhandle, \ (x)->dkim_closure, y) #define DKIM_FREE(x,y) dkim_mfree((x)->dkim_libhandle, \ (x)->dkim_closure, y) extern void *dkim_malloc __P((DKIM_LIB *, void *, size_t)); extern void dkim_mfree __P((DKIM_LIB *, void *, void *)); extern unsigned char *dkim_strdup __P((DKIM *, const unsigned char *, size_t)); extern DKIM_STAT dkim_tmpfile __P((DKIM *, int *, _Bool)); extern void dkim_dstring_blank __P((struct dkim_dstring *)); extern _Bool dkim_dstring_cat __P((struct dkim_dstring *, u_char *)); extern _Bool dkim_dstring_cat1 __P((struct dkim_dstring *, int)); extern _Bool dkim_dstring_catn __P((struct dkim_dstring *, u_char *, size_t)); extern _Bool dkim_dstring_copy __P((struct dkim_dstring *, u_char *)); extern void dkim_dstring_free __P((struct dkim_dstring *)); extern u_char *dkim_dstring_get __P((struct dkim_dstring *)); extern int dkim_dstring_len __P((struct dkim_dstring *)); extern struct dkim_dstring *dkim_dstring_new __P((DKIM *, int, int)); extern size_t dkim_dstring_printf __P((struct dkim_dstring *dstr, char *fmt, ...)); #endif /* _DKIM_UTIL_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim.c000066400000000000000000006414271337314105200220600ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, 2018, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* ! REENTRANT */ /* system includes */ #include #include #include #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #include #include #include #ifndef USE_GNUTLS # include #endif /* ! USE_GNUTLS */ #include #ifdef USE_TRE # ifdef TRE_PRE_080 # include # define tre_regcomp regcomp # define tre_regexec regexec # define tre_regaexec regaexec # define tre_regfree regfree # define tre_regerror regerror # else /* TRE_PRE_080 */ # include # ifndef TRE_USE_SYSTEM_REGEX_H # define regcomp tre_regcomp # define regexec tre_regexec # define regfree tre_regfree # define regerror tre_regerror # endif /* TRE_USE_SYSTEM_REGEX_H */ # endif /* TRE_PRE_080 */ #else /* USE_TRE */ # include #endif /* USE_TRE */ #ifdef __STDC__ # include #else /* __STDC__ */ # include #endif /* _STDC_ */ #ifdef USE_GNUTLS /* GnuTLS includes */ # include # include # include # include #else /* USE_GNUTLS */ /* OpenSSL includes */ # include # include # include # include # include # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "dkim-internal.h" #include "dkim-types.h" #include "dkim-tables.h" #include "dkim-keys.h" #include "dkim-report.h" #include "dkim-util.h" #include "dkim-canon.h" #include "dkim-dns.h" #ifdef QUERY_CACHE # include "dkim-cache.h" #endif /* QUERY_CACHE */ #include "util.h" #include "base64.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* prototypes */ void dkim_error __P((DKIM *, const char *, ...)); /* macros */ #define DKIM_STATE_INIT 0 #define DKIM_STATE_HEADER 1 #define DKIM_STATE_EOH1 2 #define DKIM_STATE_EOH2 3 #define DKIM_STATE_BODY 4 #define DKIM_STATE_EOM1 5 #define DKIM_STATE_EOM2 6 #define DKIM_STATE_UNUSABLE 99 #define DKIM_CHUNKSTATE_INIT 0 #define DKIM_CHUNKSTATE_HEADER 1 #define DKIM_CHUNKSTATE_BODY 2 #define DKIM_CHUNKSTATE_DONE 3 #define DKIM_CRLF_UNKNOWN (-1) #define DKIM_CRLF_LF 0 #define DKIM_CRLF_CRLF 1 #define DKIM_PHASH(x) ((x) - 32) #ifdef _FFR_DIFFHEADERS # define COST_INSERT 1 # define COST_DELETE 1 # define COST_SUBST 2 #endif /* _FFR_DIFFHEADERS */ #define BUFRSZ 1024 #define CRLF "\r\n" #define SP " " #define DEFCLOCKDRIFT 300 #define DEFMINKEYBITS 1024 #define DEFTIMEOUT 10 #define MINSIGLEN 8 /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ #ifndef T_AAAA # define T_AAAA 28 #endif /* ! T_AAAA */ /* need fast strtoul() and strtoull()? */ #ifdef NEED_FAST_STRTOUL # define strtoul(x,y,z) dkim_strtoul((x), (y), (z)) # define strtoull(x,y,z) dkim_strtoull((x), (y), (z)) #endif /* NEED_FAST_STRTOUL */ #define CLOBBER(x) if ((x) != NULL) \ { \ dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure, (x)); \ (x) = NULL; \ } #define HCLOBBER(x) if ((x) != NULL) \ { \ free((x)); \ (x) = NULL; \ } # define DSTRING_CLOBBER(x) if ((x) != NULL) \ { \ dkim_dstring_free((x)); \ (x) = NULL; \ } #ifdef USE_GNUTLS # define KEY_CLOBBER(x) if ((x) != NULL) \ { \ gnutls_x509_privkey_deinit((x)); \ (x) = NULL; \ } # define PUBKEY_CLOBBER(x) if ((x) != NULL) \ { \ gnutls_pubkey_deinit((x)); \ (x) = NULL; \ } # define PRIVKEY_CLOBBER(x) if ((x) != NULL) \ { \ gnutls_privkey_deinit((x)); \ (x) = NULL; \ } #else /* USE_GNUTLS */ # define BIO_CLOBBER(x) if ((x) != NULL) \ { \ BIO_free((x)); \ (x) = NULL; \ } # define RSA_CLOBBER(x) if ((x) != NULL) \ { \ RSA_free((x)); \ (x) = NULL; \ } # define EVP_CLOBBER(x) if ((x) != NULL) \ { \ EVP_PKEY_free((x)); \ (x) = NULL; \ } #endif /* ! USE_GNUTLS */ /* macros */ #define DKIM_ISLWSP(x) ((x) == 011 || (x) == 013 || (x) == 014 || (x) == 040) /* recommended list of headers to sign, from RFC6376 Section 5.4 */ const u_char *dkim_should_signhdrs[] = { "from", "reply-to", "subject", "date", "to", "cc", "resent-date", "resent-from", "resent-sender", "resent-to", "resent-cc", "in-reply-to", "references", "list-id", "list-help", "list-unsubscribe", "list-subscribe", "list-post", "list-owner", "list-archive", NULL }; /* recommended list of headers not to sign, from RFC6376 Section 5.4 */ const u_char *dkim_should_not_signhdrs[] = { "return-path", "received", "comments", "keywords", NULL }; /* required list of headers to sign */ const u_char *dkim_required_signhdrs[] = { "from", NULL }; /* ========================= PRIVATE SECTION ========================= */ /* ** DKIM_SET_FREE -- destroy a DKIM_SET ** ** Parameters: ** dkim -- DKIM context ** set -- the set to destroy ** ** Return value: ** None */ static void dkim_set_free(DKIM *dkim, DKIM_SET *set) { int c; DKIM_PLIST *plist; DKIM_PLIST *pnext; assert(set != NULL); for (c = 0; c < NPRINTABLE; c++) { for (plist = set->set_plist[c]; plist != NULL; plist = pnext) { pnext = plist->plist_next; CLOBBER(plist); } } CLOBBER(set->set_data); CLOBBER(set); } /* ** DKIM_SET_FIRST -- return first set in a context ** ** Parameters: ** dkim -- DKIM context ** type -- type to find, or DKIM_SETTYPE_ANY ** ** Return value: ** Pointer to the first DKIM_SET in the context, or NULL if none. */ static DKIM_SET * dkim_set_first(DKIM *dkim, dkim_set_t type) { DKIM_SET *set; assert(dkim != NULL); if (type == DKIM_SETTYPE_ANY) return dkim->dkim_sethead; for (set = dkim->dkim_sethead; set != NULL; set = set->set_next) { if (set->set_type == type) return set; } return NULL; } /* ** DKIM_SET_NEXT -- return next set in a context ** ** Parameters: ** set -- last set reported (i.e. starting point for this search) ** type -- type to find, or DKIM_SETTYPE_ANY ** ** Return value: ** Pointer to the next DKIM_SET in the context, or NULL if none. */ static DKIM_SET * dkim_set_next(DKIM_SET *cur, dkim_set_t type) { DKIM_SET *set; assert(cur != NULL); if (type == DKIM_SETTYPE_ANY) return cur->set_next; for (set = cur->set_next; set != NULL; set = set->set_next) { if (set->set_type == type) return set; } return NULL; } /* ** DKIM_PARAM_GET -- get a parameter from a set ** ** Parameters: ** set -- set to search ** param -- parameter to find ** ** Return value: ** Pointer to the parameter requested, or NULL if it's not in the set. */ static u_char * dkim_param_get(DKIM_SET *set, u_char *param) { DKIM_PLIST *plist; assert(set != NULL); assert(param != NULL); for (plist = set->set_plist[DKIM_PHASH(param[0])]; plist != NULL; plist = plist->plist_next) { if (strcmp((char *) plist->plist_param, (char *) param) == 0) return plist->plist_value; } return NULL; } /* ** DKIM_ADD_PLIST -- add an entry to a parameter-value set ** ** Parameters: ** dkim -- DKIM context in which this is performed ** set -- set to modify ** param -- parameter ** value -- value ** force -- override existing value, if any ** ** Return value: ** 0 on success, -1 on failure. ** ** Notes: ** Data is not copied; a reference to it is stored. */ static int dkim_add_plist(DKIM *dkim, DKIM_SET *set, u_char *param, u_char *value, _Bool force) { DKIM_PLIST *plist; assert(dkim != NULL); assert(set != NULL); assert(param != NULL); assert(value != NULL); if (!isprint(param[0])) { dkim_error(dkim, "invalid parameter '%s'", param); return -1; } /* see if we have one already */ for (plist = set->set_plist[DKIM_PHASH(param[0])]; plist != NULL; plist = plist->plist_next) { if (strcasecmp((char *) plist->plist_param, (char *) param) == 0) break; } /* nope; make one and connect it */ if (plist == NULL) { int n; plist = (DKIM_PLIST *) DKIM_MALLOC(dkim, sizeof(DKIM_PLIST)); if (plist == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(DKIM_PLIST)); return -1; } force = TRUE; n = DKIM_PHASH(param[0]); plist->plist_next = set->set_plist[n]; set->set_plist[n] = plist; plist->plist_param = param; } /* set the value if "force" was set (or this was a new entry) */ if (force) plist->plist_value = value; return 0; } /* ** DKIM_PROCESS_SET -- process a parameter set, i.e. a string of the form ** param=value[; param=value]* ** ** Parameters: ** dkim -- DKIM context in which this is performed ** type -- a DKIM_SETTYPE constant ** str -- string to be scanned ** len -- number of bytes available at "str" ** udata -- arbitrary user data (not used) ** syntax -- only check syntax and don't add 'set' to dkim handle set ** list if TRUE ** name -- an optional "name" for this set ** ** Return value: ** A DKIM_STAT constant. */ DKIM_STAT dkim_process_set(DKIM *dkim, dkim_set_t type, u_char *str, size_t len, void *udata, _Bool syntax, const char *name) { _Bool spaced; int state; int status; u_char *p; u_char *param; u_char *value; u_char *hcopy; DKIM_SET *set; const char *settype; assert(dkim != NULL); assert(str != NULL); assert(type == DKIM_SETTYPE_SIGNATURE || type == DKIM_SETTYPE_SIGREPORT || type == DKIM_SETTYPE_KEY); param = NULL; value = NULL; state = 0; spaced = FALSE; hcopy = (u_char *) DKIM_MALLOC(dkim, len + 1); if (hcopy == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", len + 1); return DKIM_STAT_INTERNAL; } strlcpy((char *) hcopy, (char *) str, len + 1); set = (DKIM_SET *) DKIM_MALLOC(dkim, sizeof(DKIM_SET)); if (set == NULL) { DKIM_FREE(dkim, hcopy); dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(DKIM_SET)); return DKIM_STAT_INTERNAL; } set->set_type = type; settype = dkim_code_to_name(settypes, type); set->set_name = name; #ifdef _FFR_CONDITIONAL set->set_minv = 1; #endif /* _FFR_CONDITIONAL */ if (!syntax) { if (dkim->dkim_sethead == NULL) dkim->dkim_sethead = set; else dkim->dkim_settail->set_next = set; dkim->dkim_settail = set; } set->set_next = NULL; memset(&set->set_plist, '\0', sizeof set->set_plist); set->set_data = hcopy; set->set_udata = udata; set->set_bad = FALSE; for (p = hcopy; *p != '\0'; p++) { if (!isascii(*p) || (!isprint(*p) && !isspace(*p))) { dkim_error(dkim, "invalid character (ASCII 0x%02x at offset %d) in %s data", *p, p - hcopy, settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } switch (state) { case 0: /* before param */ if (isspace(*p)) { continue; } #ifdef _FFR_CONDITIONAL else if (isalnum(*p) || *p == '!') #else /* _FFR_CONDITIONAL */ else if (isalnum(*p)) #endif /* _FFR_CONDITIONAL */ { #ifdef _FFR_CONDITIONAL if (*p == '!') set->set_minv = 2; #endif /* _FFR_CONDITIONAL */ param = p; state = 1; } else { dkim_error(dkim, "syntax error in %s data (ASCII 0x%02x at offset %d)", settype, *p, p - hcopy); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } break; case 1: /* in param */ if (isspace(*p)) { spaced = TRUE; } else if (*p == '=') { *p = '\0'; state = 2; spaced = FALSE; } else if (*p == ';' || spaced) { dkim_error(dkim, "syntax error in %s data (ASCII 0x%02x at offset %d)", settype, *p, p - hcopy); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } break; case 2: /* before value */ if (isspace(*p)) { continue; } else if (*p == ';') /* empty value */ { *p = '\0'; value = p; /* collapse the parameter */ dkim_collapse(param); /* create the DKIM_PLIST entry */ status = dkim_add_plist(dkim, set, param, value, TRUE); if (status == -1) { if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } /* reset */ param = NULL; value = NULL; state = 0; } else { value = p; state = 3; } break; case 3: /* in value */ if (*p == ';') { *p = '\0'; /* collapse the parameter and value */ dkim_collapse(param); dkim_collapse(value); /* create the DKIM_PLIST entry */ status = dkim_add_plist(dkim, set, param, value, TRUE); if (status == -1) { if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } /* reset */ param = NULL; value = NULL; state = 0; } break; default: /* shouldn't happen */ assert(0); } } switch (state) { case 0: /* before param */ case 3: /* in value */ /* parse the data found, if any */ if (value != NULL) { /* collapse the parameter and value */ dkim_collapse(param); dkim_collapse(value); /* create the DKIM_PLIST entry */ status = dkim_add_plist(dkim, set, param, value, TRUE); if (status == -1) { if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } } break; case 2: /* before value */ /* create an empty DKIM_PLIST entry */ status = dkim_add_plist(dkim, set, param, (u_char *) "", TRUE); if (status == -1) { if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } break; case 1: /* after param */ dkim_error(dkim, "tag without value at end of %s data", settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; default: /* shouldn't happen */ assert(0); } /* load up defaults, assert requirements */ switch (set->set_type) { case DKIM_SETTYPE_SIGREPORT: /* check validity of "rp" */ value = dkim_param_get(set, (u_char *) "rp"); if (value != NULL) { unsigned int tmp = 0; tmp = (unsigned int) strtoul(value, (char **) &p, 10); if (tmp > 100 || *p != '\0') { dkim_error(dkim, "invalid parameter(s) in %s data", settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } } break; case DKIM_SETTYPE_SIGNATURE: /* make sure required stuff is here */ if (dkim_param_get(set, (u_char *) "s") == NULL || dkim_param_get(set, (u_char *) "h") == NULL || dkim_param_get(set, (u_char *) "d") == NULL || dkim_param_get(set, (u_char *) "b") == NULL || dkim_param_get(set, (u_char *) "v") == NULL || dkim_param_get(set, (u_char *) "a") == NULL) { dkim_error(dkim, "missing parameter(s) in %s data", settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } #ifdef _FFR_CONDITIONAL /* confirm we have the right signature version */ if (set->set_minv > 1) { uint64_t tmp = 0; char *end; DKIM_PLIST *plist; value = dkim_param_get(set, (u_char *) "v"); errno = 0; tmp = strtoull((char *) value, &end, 10); if (tmp == 0 || errno != 0 || *end != '\0') { dkim_error(dkim, "invalid \"v\" value in %s data", settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } if (tmp < set->set_minv) { dkim_error(dkim, "version %s %s too low for parameters used", value, settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } /* ensure all mandatory tags are supported */ for (plist = set->set_plist[DKIM_PHASH('!')]; plist != NULL; plist = plist->plist_next) { if (dkim_name_to_code(mandatory, plist->plist_param) == -1) { dkim_error(dkim, "unsupported mandatory tag %s", plist->plist_param); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_CANTVRFY; } } } value = dkim_param_get(set, (u_char *) "!cd"); if (value != NULL) { char *d; d = dkim_param_get(set, (u_char *) "d"); if (strcasecmp(value, d) == 0) { dkim_error(dkim, "conditional signature is self-referencing"); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } } #endif /* _FFR_CONDITIONAL */ /* test validity of "t" and "x" */ value = dkim_param_get(set, (u_char *) "t"); if (value != NULL) { uint64_t tmp = 0; char *end; errno = 0; if (value[0] == '-') { errno = ERANGE; tmp = (uint64_t) -1; } else if (value[0] == '\0') { errno = EINVAL; tmp = (uint64_t) -1; } else { tmp = strtoull((char *) value, &end, 10); } if (tmp == (uint64_t) -1 || errno != 0 || *end != '\0') { dkim_error(dkim, "invalid \"t\" value in %s data", settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } } value = dkim_param_get(set, (u_char *) "x"); if (value != NULL) { uint64_t tmp = 0; char *end; errno = 0; if (value[0] == '-') { errno = ERANGE; tmp = (uint64_t) -1; } else if (value[0] == '\0') { errno = EINVAL; tmp = (uint64_t) -1; } else { tmp = strtoull((char *) value, &end, 10); } if (tmp == (uint64_t) -1 || errno != 0 || *end != '\0') { dkim_error(dkim, "invalid \"x\" value in %s data", settype); if (syntax) dkim_set_free(dkim, set); else set->set_bad = TRUE; return DKIM_STAT_SYNTAX; } } if (syntax) { dkim_set_free(dkim, set); return DKIM_STAT_OK; } /* default for "c" */ status = dkim_add_plist(dkim, set, (u_char *) "c", (u_char *) "simple/simple", FALSE); if (status == -1) { set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } /* default for "q" */ status = dkim_add_plist(dkim, set, (u_char *) "q", (u_char *) "dns/txt", FALSE); if (status == -1) { set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } break; case DKIM_SETTYPE_KEY: if (syntax) { dkim_set_free(dkim, set); return DKIM_STAT_OK; } status = dkim_add_plist(dkim, set, (u_char *) "k", (u_char *) "rsa", FALSE); if (status == -1) { set->set_bad = TRUE; return DKIM_STAT_INTERNAL; } break; default: assert(0); } return DKIM_STAT_OK; } /* ** DKIM_LOAD_SSL_ERRORS -- suck out any OpenSSL errors queued in the thread ** and attach them to the DKIM handle ** ** Parameters: ** dkim -- DKIM handle to update ** status -- status code (not used for OpenSSL) ** ** Return value: ** None. */ static void dkim_load_ssl_errors(DKIM *dkim, int status) { assert(dkim != NULL); if (dkim->dkim_sslerrbuf == NULL) { dkim->dkim_sslerrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); } #ifdef USE_GNUTLS if (dkim->dkim_sslerrbuf != NULL) { if (dkim_dstring_len(dkim->dkim_sslerrbuf) > 0) dkim_dstring_cat(dkim->dkim_sslerrbuf, "; "); dkim_dstring_cat(dkim->dkim_sslerrbuf, (char *) gnutls_strerror(status)); } #else /* USE_GNUTLS */ /* log any queued SSL error messages */ if (dkim->dkim_sslerrbuf != NULL && ERR_peek_error() != 0) { int n; int saveerr; u_long e; char tmp[BUFRSZ + 1]; saveerr = errno; for (n = 0; ; n++) { e = ERR_get_error(); if (e == 0) break; memset(tmp, '\0', sizeof tmp); (void) ERR_error_string_n(e, tmp, sizeof tmp); if (n != 0) { dkim_dstring_catn(dkim->dkim_sslerrbuf, "; ", 2); } dkim_dstring_cat(dkim->dkim_sslerrbuf, tmp); } errno = saveerr; } #endif /* USE_GNUTLS */ } /* ** DKIM_SIG_LOAD_SSL_ERRORS -- suck out any OpenSSL errors queued in the thread ** and attach them to the signature ** ** Parameters: ** dkim -- DKIM handle in which to allocate storage ** sig -- signature to update ** status -- status code (not used for OpenSSL) ** ** Return value: ** None. */ static void dkim_sig_load_ssl_errors(DKIM *dkim, DKIM_SIGINFO *sig, int status) { assert(dkim != NULL); assert(sig != NULL); if (sig->sig_sslerrbuf == NULL) sig->sig_sslerrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); #ifdef USE_GNUTLS if (sig->sig_sslerrbuf != NULL) { if (dkim_dstring_len(sig->sig_sslerrbuf) > 0) dkim_dstring_cat(sig->sig_sslerrbuf, "; "); dkim_dstring_cat(sig->sig_sslerrbuf, (char *) gnutls_strerror(status)); } #else /* USE_GNUTLS */ /* log any queued SSL error messages */ if (ERR_peek_error() != 0) { int n; int saveerr; u_long e; char tmp[BUFRSZ + 1]; saveerr = errno; for (n = 0; ; n++) { e = ERR_get_error(); if (e == 0) break; memset(tmp, '\0', sizeof tmp); (void) ERR_error_string_n(e, tmp, sizeof tmp); if (n != 0) { dkim_dstring_catn(sig->sig_sslerrbuf, "; ", 2); } dkim_dstring_cat(sig->sig_sslerrbuf, tmp); } errno = saveerr; } #endif /* ! USE_GNUTLS */ } /* ** DKIM_PRIVKEY_LOAD -- attempt to load a private key for later use ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_privkey_load(DKIM *dkim) { #ifdef USE_GNUTLS int status; #endif /* USE_GNUTLS */ struct dkim_crypto *crypto; assert(dkim != NULL); if (dkim->dkim_mode != DKIM_MODE_SIGN) return DKIM_STAT_INVALID; if (dkim->dkim_signalg != DKIM_SIGN_RSASHA1 && dkim->dkim_signalg != DKIM_SIGN_RSASHA256 && dkim->dkim_signalg != DKIM_SIGN_ED25519SHA256) return DKIM_STAT_INVALID; crypto = (struct dkim_crypto *) dkim->dkim_keydata; if (crypto == NULL) { crypto = DKIM_MALLOC(dkim, sizeof(struct dkim_crypto)); if (crypto == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_crypto)); return DKIM_STAT_NORESOURCE; } memset(crypto, '\0', sizeof(struct dkim_crypto)); } dkim->dkim_keydata = crypto; #ifdef USE_GNUTLS crypto->crypto_keydata.data = dkim->dkim_key; crypto->crypto_keydata.size = dkim->dkim_keylen; #else /* USE_GNUTLS */ if (crypto->crypto_keydata == NULL) { crypto->crypto_keydata = BIO_new_mem_buf(dkim->dkim_key, dkim->dkim_keylen); if (crypto->crypto_keydata == NULL) { dkim_error(dkim, "BIO_new_mem_buf() failed"); return DKIM_STAT_NORESOURCE; } } #endif /* USE_GNUTLS */ #ifdef USE_GNUTLS status = gnutls_x509_privkey_init(&crypto->crypto_key); if (status != GNUTLS_E_SUCCESS) { dkim_load_ssl_errors(dkim, status); dkim_error(dkim, "gnutls_x509_privkey_init() failed"); return DKIM_STAT_NORESOURCE; } if (strncmp((char *) dkim->dkim_key, "-----", 5) == 0) { /* PEM */ status = gnutls_x509_privkey_import(crypto->crypto_key, &crypto->crypto_keydata, GNUTLS_X509_FMT_PEM); } else { status = gnutls_x509_privkey_import(crypto->crypto_key, &crypto->crypto_keydata, GNUTLS_X509_FMT_DER); } if (status != GNUTLS_E_SUCCESS) { dkim_load_ssl_errors(dkim, status); dkim_error(dkim, "gnutls_x509_privkey_import() failed"); return DKIM_STAT_NORESOURCE; } status = gnutls_privkey_init(&crypto->crypto_privkey); if (status != GNUTLS_E_SUCCESS) { dkim_load_ssl_errors(dkim, status); dkim_error(dkim, "gnutls_privkey_init() failed"); return DKIM_STAT_NORESOURCE; } status = gnutls_privkey_import_x509(crypto->crypto_privkey, crypto->crypto_key, 0); if (status != GNUTLS_E_SUCCESS) { dkim_load_ssl_errors(dkim, status); dkim_error(dkim, "gnutls_privkey_import_x509() failed"); (void) gnutls_privkey_deinit(crypto->crypto_privkey); return DKIM_STAT_NORESOURCE; } (void) gnutls_privkey_get_pk_algorithm(crypto->crypto_privkey, &crypto->crypto_keysize); #else /* USE_GNUTLS */ if (strncmp((char *) dkim->dkim_key, "-----", 5) == 0) { /* PEM */ crypto->crypto_pkey = PEM_read_bio_PrivateKey(crypto->crypto_keydata, NULL, NULL, NULL); if (crypto->crypto_pkey == NULL) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "PEM_read_bio_PrivateKey() failed"); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_NORESOURCE; } } else { /* DER */ crypto->crypto_pkey = d2i_PrivateKey_bio(crypto->crypto_keydata, NULL); if (crypto->crypto_pkey == NULL) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "d2i_PrivateKey_bio() failed"); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_NORESOURCE; } } if (dkim->dkim_signalg == DKIM_SIGN_ED25519SHA256) { crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey) * 8; } else { crypto->crypto_key = EVP_PKEY_get1_RSA(crypto->crypto_pkey); if (crypto->crypto_key == NULL) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "EVP_PKEY_get1_RSA() failed"); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_NORESOURCE; } crypto->crypto_keysize = RSA_size(crypto->crypto_key) * 8; crypto->crypto_pad = RSA_PKCS1_PADDING; } crypto->crypto_outlen = crypto->crypto_keysize / 8; crypto->crypto_out = DKIM_MALLOC(dkim, crypto->crypto_outlen); if (crypto->crypto_out == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", crypto->crypto_keysize / 8); RSA_free(crypto->crypto_key); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_NORESOURCE; } #endif /* USE_GNUTLS */ return DKIM_STAT_OK; } /* ** DKIM_CHECK_REQUIREDHDRS -- see if all requried headers are present ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to the name of a header that's absent, or NULL if all ** are present. */ static const unsigned char * dkim_check_requiredhdrs(DKIM *dkim) { _Bool found; int c; size_t len; struct dkim_header *hdr; u_char **required_signhdrs; assert(dkim != NULL); required_signhdrs = dkim->dkim_libhandle->dkiml_requiredhdrs; for (c = 0; required_signhdrs[c] != NULL; c++) { found = FALSE; len = strlen((char *) required_signhdrs[c]); for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { if (hdr->hdr_namelen == len && strncasecmp((char *) hdr->hdr_text, (char *) required_signhdrs[c], len) == 0) { found = TRUE; break; } } if (!found) return required_signhdrs[c]; } return NULL; } /* ** DKIM_SET_GETUDATA -- retrieve user data associated with a set ** ** Parameters: ** set -- a DKIM_SET handle ** ** Return value: ** Stored opaque handle, if any; NULL otherwise. */ static void * dkim_set_getudata(DKIM_SET *set) { assert(set != NULL); return set->set_udata; } /* ** DKIM_GET_HEADER -- find a header in a queue of headers ** ** Parameters: ** dkim -- DKIM handle ** name -- name of the header to find ** namelen -- length of the header name at "name" (or 0) ** inst -- instance to find (0 == first/any) ** ** Return value: ** Pointer to a (struct dkim_header), or NULL if not found. */ static struct dkim_header * dkim_get_header(DKIM *dkim, u_char *name, size_t namelen, int inst) { size_t len; struct dkim_header *hdr; assert(dkim != NULL); assert(name != NULL); if (namelen == 0) len = strlen((char *) name); else len = namelen; for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { if (hdr->hdr_namelen == len && strncasecmp((char *) hdr->hdr_text, (char *) name, len) == 0) { if (inst == 0) return hdr; else inst--; } } return NULL; } /* ** DKIM_KEY_SMTP -- return TRUE iff a parameter set defines an SMTP key ** ** Parameters: ** set -- set to be checked ** ** Return value: ** TRUE iff "set" contains an "s" parameter whose value is either ** "email" or "*". */ static _Bool dkim_key_smtp(DKIM_SET *set) { u_char *val; char *last; u_char *p; char buf[BUFRSZ + 1]; assert(set != NULL); assert(set->set_type == DKIM_SETTYPE_KEY); val = dkim_param_get(set, (u_char * ) "s"); if (val == NULL) return TRUE; strlcpy(buf, (char *) val, sizeof buf); for (p = (u_char *) strtok_r(buf, ":", &last); p != NULL; p = (u_char *) strtok_r(NULL, ":", &last)) { if (strcmp((char *) p, "*") == 0 || strcasecmp((char *) p, "email") == 0) return TRUE; } return FALSE; } /* ** DKIM_KEY_HASHOK -- return TRUE iff a signature's hash is in the approved ** list of hashes for a given key ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** hashlist -- colon-separated approved hash list ** ** Return value: ** TRUE iff a particular hash is in the approved list of hashes. */ static _Bool dkim_key_hashok(DKIM_SIGINFO *sig, u_char *hashlist) { int hashalg; u_char *x, *y; u_char tmp[BUFRSZ + 1]; assert(sig != NULL); if (hashlist == NULL) return TRUE; x = NULL; memset(tmp, '\0', sizeof tmp); y = hashlist; for (;;) { if (*y == ':' || *y == '\0') { if (x != NULL) { strlcpy((char *) tmp, (char *) x, sizeof tmp); tmp[y - x] = '\0'; hashalg = dkim_name_to_code(hashes, (char *) tmp); if (hashalg == sig->sig_hashtype) return TRUE; } x = NULL; } else if (x == NULL) { x = y; } if (*y == '\0') return FALSE; y++; } /* NOTREACHED */ } /* ** DKIM_KEY_HASHESOK -- return TRUE iff this key supports at least one ** hash method we know about (or doesn't specify) ** ** Parameters: ** hashlist -- colon-separated list of hashes (or NULL) ** ** Return value: ** TRUE iff this key supports at least one hash method we know about ** (or doesn't specify) */ static _Bool dkim_key_hashesok(DKIM_LIB *lib, u_char *hashlist) { u_char *x, *y; u_char tmp[BUFRSZ + 1]; assert(lib != NULL); if (hashlist == NULL) return TRUE; x = NULL; memset(tmp, '\0', sizeof tmp); y = hashlist; for (;;) { if (*y == ':' || *y == '\0') { if (x != NULL) { int hashcode; strlcpy((char *) tmp, (char *) x, sizeof tmp); tmp[y - x] = '\0'; hashcode = dkim_name_to_code(hashes, (char *) tmp); if (hashcode != -1 && (hashcode != DKIM_HASHTYPE_SHA256 || dkim_libfeature(lib, DKIM_FEATURE_SHA256))) return TRUE; } x = NULL; } else if (x == NULL) { x = y; } if (*y == '\0') return FALSE; y++; } /* NOTREACHED */ } /* ** DKIM_SIG_HDRLISTOK -- return TRUE iff a header list contained at least ** all of those headers which MUST be signed ** ** Parameters: ** dkim -- DKIM handle ** hdrlist -- header list to be checked ** ** Return value: ** 1 if the header list meets spec requirements, ** 0 if not, ** -1 on error */ static _Bool dkim_sig_hdrlistok(DKIM *dkim, u_char *hdrlist) { _Bool in = FALSE; _Bool found; int c; int d; int nh; u_char *p; u_char **ptrs; u_char **required_signhdrs;; u_char tmp[DKIM_MAXHEADER + 1]; assert(dkim != NULL); assert(hdrlist != NULL); strlcpy((char *) tmp, (char *) hdrlist, sizeof tmp); /* figure out how many headers were named */ c = 0; for (p = tmp; *p != '\0'; p++) { if (*p == ':') { in = FALSE; } else if (isascii(*p) && !isspace(*p) && !in) { c++; in = TRUE; } } nh = c; /* allocate an array of pointers to them */ ptrs = DKIM_MALLOC(dkim, sizeof(u_char *) * nh); if (ptrs == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(u_char *) * nh); return -1; } /* set the pointers */ c = 0; in = FALSE; for (p = tmp; *p != '\0'; p++) { if (*p == ':') { *p = '\0'; in = FALSE; } else if (isascii(*p) && !isspace(*p) && !in) { ptrs[c++] = p; in = TRUE; } } /* verify that each required header was represented */ required_signhdrs = dkim->dkim_libhandle->dkiml_requiredhdrs; for (d = 0; ; d++) { if (required_signhdrs[d] == NULL) break; found = FALSE; for (c = 0; c < nh; c++) { if (strcasecmp((char *) required_signhdrs[d], (char *) ptrs[c]) == 0) { found = TRUE; break; } } if (!found) { DKIM_FREE(dkim, ptrs); return 0; } } DKIM_FREE(dkim, ptrs); return 1; } /* ** DKIM_SIG_DOMAINOK -- return TRUE iff a signature appears to have valid ** domain correlation; that is, "i" must be the same ** domain as or a subdomain of "d" ** ** Parameters: ** dkim -- DKIM handle ** set -- signature set to be checked ** ** Return value: ** TRUE iff the "i" parameter and the "d" parameter match up. */ static _Bool dkim_sig_domainok(DKIM *dkim, DKIM_SET *set) { char *at; char *dot; u_char *i; u_char *d; u_char addr[MAXADDRESS + 1]; assert(dkim != NULL); assert(set != NULL); assert(set->set_type == DKIM_SETTYPE_SIGNATURE); i = dkim_param_get(set, (u_char *) "i"); d = dkim_param_get(set, (u_char *) "d"); assert(d != NULL); memset(addr, '\0', sizeof addr); if (i == NULL) snprintf((char *) addr, sizeof addr, "@%s", d); else dkim_qp_decode(i, addr, sizeof addr - 1); at = strchr((char *) addr, '@'); if (at == NULL) return FALSE; if (strcasecmp(at + 1, (char *) d) == 0) return TRUE; for (dot = strchr(at, '.'); dot != NULL; dot = strchr(dot + 1, '.')) { if (strcasecmp(dot + 1, (char *) d) == 0) { dkim->dkim_subdomain = TRUE; return TRUE; } } return FALSE; } /* ** DKIM_SIG_EXPIRED -- return TRUE iff a signature appears to have expired ** ** Parameters: ** set -- signature set to be checked ** drift -- seconds of drift allowed ** ** Return value: ** TRUE iff "set" contains an "x=" parameter which indicates a time ** which has passed. ** ** Notes: ** Syntax is not checked here. It's checked in dkim_process_set(). */ static _Bool dkim_sig_expired(DKIM_SET *set, uint64_t drift) { time_t now; uint64_t expire; uint64_t nowl; u_char *val; assert(set != NULL); assert(set->set_type == DKIM_SETTYPE_SIGNATURE); val = dkim_param_get(set, (u_char *) "x"); if (val == NULL) return FALSE; if (sizeof(uint64_t) == sizeof(unsigned long long)) expire = strtoull((char *) val, NULL, 10); else if (sizeof(uint64_t) == sizeof(unsigned long)) expire = strtoul((char *) val, NULL, 10); else expire = (unsigned int) strtoul((char *) val, NULL, 10); (void) time(&now); nowl = (uint64_t) now; return (nowl >= expire + drift); } /* ** DKIM_SIG_TIMESTAMPSOK -- return TRUE iff a signature appears to have ** both a timestamp and an expiration date and they ** are properly ordered ** ** Parameters: ** set -- signature set to be checked ** ** Return value: ** TRUE: - "set" contains both a "t=" parameter and an "x=" parameter ** and the latter is greater than the former ** - "set" is missing either "t=" or "x=" (or both) ** FALSE: otherwise ** ** Notes: ** Syntax is not checked here. It's checked in dkim_process_set(). */ static _Bool dkim_sig_timestampsok(DKIM_SET *set) { uint64_t signtime; uint64_t expire; u_char *val; assert(set != NULL); assert(set->set_type == DKIM_SETTYPE_SIGNATURE); val = dkim_param_get(set, (u_char *) "t"); if (val == NULL) return TRUE; if (sizeof(uint64_t) == sizeof(unsigned long long)) signtime = strtoull((char *) val, NULL, 10); else if (sizeof(uint64_t) == sizeof(unsigned long)) signtime = strtoul((char *) val, NULL, 10); else signtime = (unsigned int) strtoul((char *) val, NULL, 10); val = dkim_param_get(set, (u_char *) "x"); if (val == NULL) return TRUE; if (sizeof(uint64_t) == sizeof(unsigned long long)) expire = strtoull((char *) val, NULL, 10); else if (sizeof(uint64_t) == sizeof(unsigned long)) expire = strtoul((char *) val, NULL, 10); else expire = (unsigned int) strtoul((char *) val, NULL, 10); return (signtime < expire); } /* ** DKIM_SIG_FUTURE -- return TRUE iff a signature appears to have been ** generated in the future ** ** Parameters: ** set -- signature set to be checked ** drift -- seconds of drift allowed ** ** Return value: ** TRUE iff "set" contains a "t=" parameter which indicates a time ** in the future. ** ** Notes: ** Syntax is not checked here. It's checked in dkim_process_set(). */ static _Bool dkim_sig_future(DKIM_SET *set, uint64_t drift) { uint64_t signtime; uint64_t nowl; time_t now; u_char *val; assert(set != NULL); assert(set->set_type == DKIM_SETTYPE_SIGNATURE); val = dkim_param_get(set, (u_char *) "t"); if (val == NULL) return FALSE; if (sizeof(uint64_t) == sizeof(unsigned long long)) signtime = strtoull((char *) val, NULL, 10); else if (sizeof(uint64_t) == sizeof(unsigned long)) signtime = strtoul((char *) val, NULL, 10); else signtime = (unsigned int) strtoul((char *) val, NULL, 10); (void) time(&now); nowl = (uint64_t) now; return (nowl < signtime - drift); } /* ** DKIM_SIG_VERSIONOK -- return TRUE iff a signature appears to have a version ** we can accept ** ** Parameters: ** dkim -- DKIM handle ** set -- signature set to be checked ** ** Return value: ** TRUE iff "set" appears to be based on a version of DKIM that is ** supported by this API. */ static _Bool dkim_sig_versionok(DKIM *dkim, DKIM_SET *set) { char *v; assert(set != NULL); assert(set->set_type == DKIM_SETTYPE_SIGNATURE); v = (char *) dkim_param_get(set, (u_char *) "v"); assert(v != NULL); /* check for DKIM_VERSION_SIG */ if (strcmp(v, DKIM_VERSION_SIG) == 0) return TRUE; #ifdef _FFR_CONDITIONAL if (strcmp(v, DKIM_VERSION_SIG2) == 0) return TRUE; #endif /* _FFR_CONDITIONAL */ /* check for DKIM_VERSION_SIGOLD if allowed */ if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_ACCEPTV05) && strcmp(v, DKIM_VERSION_SIGOLD) == 0) return TRUE; return FALSE; } /* ** DKIM_SIGLIST_SETUP -- create a signature list and load the elements ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_siglist_setup(DKIM *dkim) { _Bool bsh; int c; int hashtype = DKIM_HASHTYPE_UNKNOWN; int hstatus; size_t b64siglen; size_t len; DKIM_STAT status; ssize_t signlen = (ssize_t) -1; uint64_t drift; dkim_canon_t bodycanon; dkim_canon_t hdrcanon; dkim_alg_t signalg; DKIM_SET *set; DKIM_LIB *lib; DKIM_CANON *hc; DKIM_CANON *bc; u_char *param; u_char *hdrlist; assert(dkim != NULL); lib = dkim->dkim_libhandle; drift = lib->dkiml_clockdrift; bsh = ((lib->dkiml_flags & DKIM_LIBFLAGS_BADSIGHANDLES) != 0); len = dkim->dkim_sigcount * sizeof(DKIM_SIGINFO *); dkim->dkim_siglist = DKIM_MALLOC(dkim, len); if (dkim->dkim_siglist == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", len); return DKIM_STAT_NORESOURCE; } /* allocate the siginfo elements */ for (c = 0; c < dkim->dkim_sigcount; c++) { dkim->dkim_siglist[c] = DKIM_MALLOC(dkim, sizeof(DKIM_SIGINFO)); if (dkim->dkim_siglist[c] == NULL) { int n; dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(DKIM_SIGINFO)); for (n = 0; n < c; n++) DKIM_FREE(dkim, dkim->dkim_siglist[n]); return DKIM_STAT_NORESOURCE; } memset(dkim->dkim_siglist[c], '\0', sizeof(DKIM_SIGINFO)); } /* populate the elements */ for (set = dkim_set_first(dkim, DKIM_SETTYPE_SIGNATURE), c = 0; set != NULL && c < dkim->dkim_sigcount; set = dkim_set_next(set, DKIM_SETTYPE_SIGNATURE), c++) { /* cope with bad ones */ if (set->set_bad && !bsh) { c--; continue; } /* defaults */ dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_UNKNOWN; dkim->dkim_siglist[c]->sig_dnssec_key = DKIM_DNSSEC_UNKNOWN; /* store the set */ dkim->dkim_siglist[c]->sig_taglist = set; /* override query method? */ if (lib->dkiml_querymethod != DKIM_QUERY_UNKNOWN) dkim->dkim_siglist[c]->sig_query = lib->dkiml_querymethod; /* critical stuff: signing domain */ param = dkim_param_get(set, (u_char *) "d"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_D; continue; } else if (param[0] == '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EMPTY_D; continue; } dkim->dkim_siglist[c]->sig_domain = param; /* critical stuff: selector */ param = dkim_param_get(set, (u_char *) "s"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_S; continue; } else if (param[0] == '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EMPTY_S; continue; } dkim->dkim_siglist[c]->sig_selector = param; /* some basic checks first */ param = dkim_param_get(set, (u_char *) "v"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_V; continue; } else if (param[0] == '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EMPTY_V; continue; } else if (!dkim_sig_versionok(dkim, set)) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_VERSION; continue; } else if (!dkim_sig_domainok(dkim, set)) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_DOMAIN; continue; } else if (dkim_sig_expired(set, drift)) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EXPIRED; continue; } else if (dkim_sig_future(set, drift)) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_FUTURE; continue; } else if (!dkim_sig_timestampsok(set)) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_TIMESTAMPS; continue; } /* determine canonicalizations */ param = dkim_param_get(set, (u_char *) "c"); if (param == NULL) { hdrcanon = DKIM_CANON_SIMPLE; bodycanon = DKIM_CANON_SIMPLE; } else { char *q; char value[BUFRSZ + 1]; strlcpy(value, (char *) param, sizeof value); q = strchr(value, '/'); if (q != NULL) *q = '\0'; hdrcanon = dkim_name_to_code(canonicalizations, value); if (hdrcanon == -1) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_HC; continue; } if (q == NULL) { bodycanon = DKIM_CANON_SIMPLE; } else { bodycanon = dkim_name_to_code(canonicalizations, q + 1); if (bodycanon == -1) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_BC; continue; } } } /* determine hash type */ param = dkim_param_get(set, (u_char *) "a"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_A; continue; } else { signalg = dkim_name_to_code(algorithms, (char *) param); if (signalg == -1) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_A; continue; } switch (signalg) { case DKIM_SIGN_RSASHA1: hashtype = DKIM_HASHTYPE_SHA1; break; case DKIM_SIGN_RSASHA256: if (dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { hashtype = DKIM_HASHTYPE_SHA256; } else { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_A; continue; } break; case DKIM_SIGN_ED25519SHA256: if (dkim_libfeature(lib, DKIM_FEATURE_ED25519)) { hashtype = DKIM_HASHTYPE_SHA256; } else { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_A; continue; } break; default: assert(0); /* NOTREACHED */ } dkim->dkim_siglist[c]->sig_signalg = signalg; dkim->dkim_siglist[c]->sig_hashtype = hashtype; } /* determine header list */ param = dkim_param_get(set, (u_char *) "h"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_H; continue; } else if (param[0] == '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EMPTY_H; continue; } hstatus = dkim_sig_hdrlistok(dkim, param); if (hstatus == 0) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_H; continue; } else if (hstatus == -1) { return DKIM_STAT_NORESOURCE; } hdrlist = param; /* determine signing length */ signlen = (ssize_t) -1; param = dkim_param_get(set, (u_char *) "l"); if (param != NULL) { char *q; errno = 0; if (param[0] == '-') { errno = ERANGE; signlen = ULONG_MAX; } else { signlen = (ssize_t) strtoul((char *) param, &q, 10); } if (signlen == ULONG_MAX || errno != 0 || *q != '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_L; continue; } } /* query method */ param = dkim_param_get(set, (u_char *) "q"); if (param != NULL) { _Bool bad_qo = FALSE; dkim_query_t q = (dkim_query_t) -1; u_char *p; char *last; u_char *opts; u_char tmp[BUFRSZ + 1]; u_char qtype[BUFRSZ + 1]; strlcpy((char *) qtype, (char *) param, sizeof qtype); for (p = (u_char *) strtok_r((char *) qtype, ":", &last); p != NULL; p = (u_char *) strtok_r(NULL, ":", &last)) { opts = (u_char *) strchr((char *) p, '/'); if (opts != NULL) { strlcpy((char *) tmp, (char *) p, sizeof tmp); p = tmp; opts = (u_char *) strchr((char *) tmp, '/'); if (opts != NULL) { *opts = '\0'; opts++; } } /* unknown type */ q = dkim_name_to_code(querytypes, (char *) p); if (q == (dkim_query_t) -1) continue; if (q == DKIM_QUERY_DNS) { /* "txt" option required */ if (opts == NULL || strcmp((char *) opts, "txt") != 0) { bad_qo = TRUE; continue; } } break; } if (dkim->dkim_libhandle->dkiml_key_lookup == NULL) { if (q == (dkim_query_t) -1) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_Q; continue; } else if (bad_qo) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_INVALID_QO; continue; } } dkim->dkim_siglist[c]->sig_query = q; } /* override query method? */ if (lib->dkiml_querymethod != DKIM_QUERY_UNKNOWN) dkim->dkim_siglist[c]->sig_query = lib->dkiml_querymethod; /* timestamp */ param = dkim_param_get(set, (u_char *) "t"); if (param == NULL) { dkim->dkim_siglist[c]->sig_timestamp = 0; } else { if (sizeof(uint64_t) == sizeof(unsigned long long)) { dkim->dkim_siglist[c]->sig_timestamp = strtoull((char *) param, NULL, 10); } else if (sizeof(uint64_t) == sizeof(unsigned long)) { dkim->dkim_siglist[c]->sig_timestamp = strtoul((char *) param, NULL, 10); } else { dkim->dkim_siglist[c]->sig_timestamp = (unsigned int) strtoul((char *) param, NULL, 10); } } /* body hash */ param = dkim_param_get(set, (u_char *) "bh"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_BH; continue; } else if (param[0] == '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EMPTY_BH; continue; } /* signature */ param = dkim_param_get(set, (u_char *) "b"); if (param == NULL) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_MISSING_B; continue; } else if (param[0] == '\0') { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_EMPTY_B; continue; } b64siglen = strlen((char *) param); dkim->dkim_siglist[c]->sig_sig = DKIM_MALLOC(dkim, b64siglen); if (dkim->dkim_siglist[c]->sig_sig == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", b64siglen); return DKIM_STAT_NORESOURCE; } status = dkim_base64_decode(param, dkim->dkim_siglist[c]->sig_sig, b64siglen); if (status < 0) { dkim->dkim_siglist[c]->sig_error = DKIM_SIGERROR_CORRUPT_B; continue; } else { dkim->dkim_siglist[c]->sig_siglen = status; } /* canonicalization handle for the headers */ status = dkim_add_canon(dkim, TRUE, hdrcanon, hashtype, hdrlist, dkim_set_getudata(set), 0, &hc); if (status != DKIM_STAT_OK) return status; dkim->dkim_siglist[c]->sig_hdrcanon = hc; dkim->dkim_siglist[c]->sig_hdrcanonalg = hdrcanon; /* canonicalization handle for the body */ status = dkim_add_canon(dkim, FALSE, bodycanon, hashtype, NULL, NULL, signlen, &bc); if (status != DKIM_STAT_OK) return status; dkim->dkim_siglist[c]->sig_bodycanon = bc; dkim->dkim_siglist[c]->sig_bodycanonalg = bodycanon; /* the rest */ dkim->dkim_siglist[c]->sig_bh = DKIM_SIGBH_UNTESTED; dkim->dkim_siglist[c]->sig_flags = 0; /* allow the user to generate its handle */ if (lib->dkiml_sig_handle != NULL) dkim->dkim_siglist[c]->sig_context = lib->dkiml_sig_handle(dkim->dkim_closure); /* populate the user handle */ if (lib->dkiml_sig_tagvalues != NULL) { u_int n; dkim_param_t pcode; struct dkim_plist *plist; void *user; user = dkim->dkim_siglist[c]->sig_context; for (n = 0; n < NPRINTABLE; n++) { for (plist = set->set_plist[n]; plist != NULL; plist = plist->plist_next) { pcode = dkim_name_to_code(sigparams, (char *) plist->plist_param); (void) lib->dkiml_sig_tagvalues(user, pcode, plist->plist_param, plist->plist_value); } } } } return DKIM_STAT_OK; } /* ** DKIM_GENSIGHDR -- generate a signature header ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** dstr -- dstring to which to write ** delim -- delimiter ** ** Return value: ** Number of bytes written to "dstr", or <= 0 on error. */ static size_t dkim_gensighdr(DKIM *dkim, DKIM_SIGINFO *sig, struct dkim_dstring *dstr, char *delim) { _Bool firsthdr; _Bool nosigner = FALSE; int n; int status; int delimlen; size_t hashlen; char *format; u_char *hash; u_char *v; struct dkim_header *hdr; u_char tmp[DKIM_MAXHEADER + 1]; u_char b64hash[DKIM_MAXHEADER + 1]; assert(dkim != NULL); assert(sig != NULL); assert(dstr != NULL); assert(delim != NULL); delimlen = strlen(delim); /* bail if we were asked to generate an invalid signature */ if (dkim->dkim_signer != NULL) { _Bool match = FALSE; u_char *sd; sd = strchr(dkim->dkim_signer, '@'); if (sd == NULL) { dkim_error(dkim, "syntax error in signer value"); return 0; } if (strcasecmp(sd + 1, sig->sig_domain) == 0) { match = TRUE; } else { for (sd = strchr(sd + 1, '.'); sd != NULL && !match; sd = strchr(sd + 1, '.')) { if (strcasecmp(sd + 1, sig->sig_domain) == 0) match = TRUE; } } if (!match) { if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_DROPSIGNER) == 0) { dkim_error(dkim, "d=/i= mismatch on signature generation"); return 0; } else { nosigner = TRUE; } } } /* ** We need to generate a DKIM-Signature: header template ** and include it in the canonicalization. */ /* basic required stuff */ if (sizeof(sig->sig_timestamp) == sizeof(unsigned long long)) format = "v=%s;%sa=%s;%sc=%s/%s;%sd=%s;%ss=%s;%st=%llu"; else if (sizeof(sig->sig_timestamp) == sizeof(unsigned long)) format = "v=%s;%sa=%s;%sc=%s/%s;%sd=%s;%ss=%s;%st=%lu"; else format = "v=%s;%sa=%s;%sc=%s/%s;%sd=%s;%ss=%s;%st=%u"; v = DKIM_VERSION_SIG; #ifdef _FFR_CONDITIONAL if (dkim->dkim_conditional != NULL) v = DKIM_VERSION_SIG2; if (dkim->dkim_xtags != NULL) { struct dkim_xtag *xt; for (xt = dkim->dkim_xtags; xt != NULL; xt = xt->xt_next) { if (xt->xt_tag[0] == '!') { v = DKIM_VERSION_SIG2; break; } } } #endif /* _FFR_CONDITIONAL */ (void) dkim_dstring_printf(dstr, format, v, delim, dkim_code_to_name(algorithms, sig->sig_signalg), delim, dkim_code_to_name(canonicalizations, sig->sig_hdrcanonalg), dkim_code_to_name(canonicalizations, sig->sig_bodycanonalg), delim, sig->sig_domain, delim, sig->sig_selector, delim, sig->sig_timestamp); if (dkim->dkim_querymethods != NULL) { _Bool firstq = TRUE; struct dkim_qmethod *q; for (q = dkim->dkim_querymethods; q != NULL; q = q->qm_next) { if (firstq) { dkim_dstring_printf(dstr, ";%sq=%s", delim, q->qm_type); } else { dkim_dstring_printf(dstr, ":%s", q->qm_type); } if (q->qm_options) { dkim_dstring_printf(dstr, "/%s", q->qm_options); } firstq = FALSE; } } if (dkim->dkim_libhandle->dkiml_sigttl != 0) { uint64_t expire; expire = sig->sig_timestamp + dkim->dkim_libhandle->dkiml_sigttl; if (sizeof(expire) == sizeof(unsigned long long)) dkim_dstring_printf(dstr, ";%sx=%llu", delim, expire); else if (sizeof(expire) == sizeof(unsigned long)) dkim_dstring_printf(dstr, ";%sx=%lu", delim, expire); else dkim_dstring_printf(dstr, ";%sx=%u", delim, expire); } if (dkim->dkim_signer != NULL && !nosigner) { dkim_dstring_printf(dstr, ";%si=%s", delim, dkim->dkim_signer); } #ifdef _FFR_CONDITIONAL if (dkim->dkim_conditional != NULL) { dkim_dstring_printf(dstr, ";%s!cd=%s", delim, dkim->dkim_conditional); } #endif /* _FFR_CONDITIONAL */ if (dkim->dkim_xtags != NULL) { struct dkim_xtag *x; for (x = dkim->dkim_xtags; x != NULL; x = x->xt_next) { dkim_dstring_printf(dstr, ";%s%s=%s", delim, x->xt_tag, x->xt_value); } } memset(b64hash, '\0', sizeof b64hash); status = dkim_canon_closebody(dkim); if (status != DKIM_STAT_OK) return 0; status = dkim_canon_getfinal(sig->sig_bodycanon, &hash, &hashlen); if (status != DKIM_STAT_OK) { dkim_error(dkim, "dkim_canon_getfinal() failed"); return (size_t) -1; } status = dkim_base64_encode(hash, hashlen, b64hash, sizeof b64hash); dkim_dstring_printf(dstr, ";%sbh=%s", delim, b64hash); /* l= */ if (dkim->dkim_partial) { dkim_dstring_printf(dstr, ";%sl=%lu", delim, (u_long) sig->sig_bodycanon->canon_wrote); } /* h= */ firsthdr = TRUE; for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { if ((hdr->hdr_flags & DKIM_HDR_SIGNED) == 0) continue; if (!firsthdr) { dkim_dstring_cat1(dstr, ':'); } else { dkim_dstring_cat1(dstr, ';'); dkim_dstring_catn(dstr, (u_char *) delim, delimlen); dkim_dstring_catn(dstr, (u_char *) "h=", 2); } firsthdr = FALSE; dkim_dstring_catn(dstr, hdr->hdr_text, hdr->hdr_namelen); } if (dkim->dkim_libhandle->dkiml_oversignhdrs != NULL && dkim->dkim_libhandle->dkiml_oversignhdrs[0] != NULL) { _Bool wrote = FALSE; if (firsthdr) { dkim_dstring_cat1(dstr, ';'); dkim_dstring_catn(dstr, delim, delimlen); dkim_dstring_catn(dstr, "h=", 2); } else { dkim_dstring_cat1(dstr, ':'); } for (n = 0; dkim->dkim_libhandle->dkiml_oversignhdrs[n] != NULL; n++) { if (dkim->dkim_libhandle->dkiml_oversignhdrs[n][0] == '\0') continue; if (wrote) dkim_dstring_cat1(dstr, ':'); dkim_dstring_cat(dstr, dkim->dkim_libhandle->dkiml_oversignhdrs[n]); wrote = TRUE; } } /* if reports were requested, stick that in too */ if (dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_REQUESTREPORTS) dkim_dstring_printf(dstr, ";%sr=y", delim); /* if diagnostic headers were requested, include 'em */ if (dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_ZTAGS) { _Bool first; int status; int len; u_char *hend; u_char *colon; unsigned char name[DKIM_MAXHEADER + 1]; dkim_dstring_cat1(dstr, ';'); dkim_dstring_catn(dstr, (u_char *) delim, delimlen); dkim_dstring_catn(dstr, (u_char *) "z=", 2); first = TRUE; for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { /* apply "skip" header and "sign" header lists */ hend = hdr->hdr_text + hdr->hdr_textlen; colon = memchr(hdr->hdr_text, ':', hdr->hdr_textlen); if (colon != NULL) { hend = colon; while (hend > hdr->hdr_text && isascii(*(hend - 1)) && isspace(*(hend - 1))) hend--; } strlcpy((char *) name, (char *) hdr->hdr_text, sizeof name); if (hend != NULL) name[hend - hdr->hdr_text] = '\0'; if (dkim->dkim_libhandle->dkiml_skipre) { status = regexec(&dkim->dkim_libhandle->dkiml_skiphdrre, (char *) name, 0, NULL, 0); if (status == 0) continue; else assert(status == REG_NOMATCH); } if (dkim->dkim_libhandle->dkiml_signre) { status = regexec(&dkim->dkim_libhandle->dkiml_hdrre, (char *) name, 0, NULL, 0); if (status == REG_NOMATCH) continue; else assert(status == 0); } if (!first) { dkim_dstring_cat1(dstr, '|'); } first = FALSE; len = dkim_qp_encode(hdr->hdr_text, tmp, sizeof tmp); if (len > 0) dkim_dstring_catn(dstr, tmp, (size_t) len); } } /* and finally, an empty b= */ dkim_dstring_cat1(dstr, ';'); dkim_dstring_catn(dstr, (u_char *) delim, delimlen); dkim_dstring_catn(dstr, (u_char *) "b=", 2); return dkim_dstring_len(dstr); } /* ** DKIM_GETSENDER -- determine sender and store it in the handle ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ static DKIM_STAT dkim_getsender(DKIM *dkim) { int c; size_t hlen; DKIM_STAT status; unsigned char *domain; unsigned char *user; struct dkim_header *sender = NULL; struct dkim_header *cur; assert(dkim != NULL); if (dkim->dkim_sender != NULL) return DKIM_STAT_OK; for (cur = dkim->dkim_hhead; cur != NULL; cur = cur->hdr_next) { if (cur->hdr_namelen == 4 && strncasecmp("from", (char *) cur->hdr_text, 4) == 0) { sender = cur; break; } } if (sender == NULL) { dkim_error(dkim, "no from header field detected"); return DKIM_STAT_SYNTAX; } dkim->dkim_senderhdr = sender; if (sender->hdr_colon == NULL) { dkim_error(dkim, "syntax error in headers"); return DKIM_STAT_SYNTAX; } dkim->dkim_sender = dkim_strdup(dkim, sender->hdr_colon + 1, 0); if (dkim->dkim_sender == NULL) return DKIM_STAT_NORESOURCE; status = dkim_mail_parse(dkim->dkim_sender, &user, &domain); if (status != 0 || domain == NULL || user == NULL || domain[0] == '\0' || user[0] == '\0') { dkim_error(dkim, "can't determine sender address"); return DKIM_STAT_SYNTAX; } if (dkim->dkim_domain == NULL) { dkim->dkim_domain = dkim_strdup(dkim, domain, 0); if (dkim->dkim_domain == NULL) return DKIM_STAT_NORESOURCE; } dkim->dkim_user = dkim_strdup(dkim, user, 0); if (dkim->dkim_user == NULL) return DKIM_STAT_NORESOURCE; return DKIM_STAT_OK; } /* ** DKIM_GET_KEY -- acquire a public key used for verification ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** test -- skip signature-specific validity checks ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_get_key(DKIM *dkim, DKIM_SIGINFO *sig, _Bool test) { _Bool gotkey = FALSE; /* key stored */ _Bool gotset = FALSE; /* set parsed */ _Bool gotreply = FALSE; /* reply received */ int status; int c; DKIM_SIGINFO *osig; struct dkim_set *set = NULL; struct dkim_set *nextset; unsigned char *p; unsigned char buf[BUFRSZ + 1]; assert(dkim != NULL); assert(sig != NULL); assert(sig->sig_selector != NULL); assert(sig->sig_domain != NULL); memset(buf, '\0', sizeof buf); /* see if one of the other signatures already has the key we need */ for (c = 0; c < dkim->dkim_sigcount; c++) { osig = dkim->dkim_siglist[c]; /* don't self-search */ if (sig == osig) continue; /* skip unprocessed signatures */ if ((osig->sig_flags & DKIM_SIGFLAG_PROCESSED) == 0) continue; /* skip unless selector and domain match */ if (strcmp((char *) osig->sig_domain, (char *) sig->sig_domain) != 0 || strcmp((char *) osig->sig_selector, (char *) sig->sig_selector) != 0) continue; /* we got a match! copy the key data (if any)... */ if (osig->sig_key != NULL) { sig->sig_key = DKIM_MALLOC(dkim, osig->sig_b64keylen); if (sig->sig_key == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", osig->sig_b64keylen); return DKIM_STAT_NORESOURCE; } memcpy(sig->sig_key, osig->sig_key, osig->sig_b64keylen); sig->sig_keylen = osig->sig_keylen; gotkey = TRUE; } /* ...and the key tag list (if any) */ if (osig->sig_keytaglist != NULL) { sig->sig_keytaglist = osig->sig_keytaglist; set = sig->sig_keytaglist; gotset = TRUE; gotreply = TRUE; } break; } /* try a local function if there was one defined */ if (!gotkey && dkim->dkim_libhandle->dkiml_key_lookup != NULL) { DKIM_CBSTAT cbstatus; cbstatus = dkim->dkim_libhandle->dkiml_key_lookup(dkim, sig, buf, sizeof buf); switch (cbstatus) { case DKIM_CBSTAT_CONTINUE: gotreply = TRUE; break; case DKIM_CBSTAT_REJECT: return DKIM_STAT_CBREJECT; case DKIM_CBSTAT_TRYAGAIN: return DKIM_STAT_CBTRYAGAIN; case DKIM_CBSTAT_NOTFOUND: return DKIM_STAT_NOKEY; case DKIM_CBSTAT_ERROR: return DKIM_STAT_CBERROR; case DKIM_CBSTAT_DEFAULT: break; default: return DKIM_STAT_CBINVALID; } } /* if no local function or it returned no result, make the query */ if (!gotreply) { /* use appropriate get method */ switch (sig->sig_query) { case DKIM_QUERY_DNS: status = (int) dkim_get_key_dns(dkim, sig, buf, sizeof buf); if (status != (int) DKIM_STAT_OK) return (DKIM_STAT) status; break; case DKIM_QUERY_FILE: status = (int) dkim_get_key_file(dkim, sig, buf, sizeof buf); if (status != (int) DKIM_STAT_OK) return (DKIM_STAT) status; break; default: assert(0); } } /* decode the payload */ if (!gotset) { if (buf[0] == '\0') { dkim_error(dkim, "empty key record"); return DKIM_STAT_SYNTAX; } status = dkim_process_set(dkim, DKIM_SETTYPE_KEY, buf, strlen((char *) buf), NULL, FALSE, NULL); if (status != DKIM_STAT_OK) return status; /* get the last key */ set = dkim_set_first(dkim, DKIM_SETTYPE_KEY); assert(set != NULL); for (;;) { nextset = dkim_set_next(set, DKIM_SETTYPE_KEY); if (nextset == NULL) break; set = nextset; } assert(set != NULL); sig->sig_keytaglist = set; } /* verify key version first */ p = dkim_param_get(set, (u_char *) "v"); if (p != NULL && strcmp((char *) p, DKIM_VERSION_KEY) != 0) { dkim_error(dkim, "invalid key version '%s'", p); sig->sig_error = DKIM_SIGERROR_KEYVERSION; return DKIM_STAT_SYNTAX; } /* then make sure the hash type is something we can handle */ p = dkim_param_get(set, (u_char *) "h"); if (!dkim_key_hashesok(dkim->dkim_libhandle, p)) { dkim_error(dkim, "unknown hash '%s'", p); sig->sig_error = DKIM_SIGERROR_KEYUNKNOWNHASH; return DKIM_STAT_SYNTAX; } /* ...and that this key is approved for this signature's hash */ else if (!test && !dkim_key_hashok(sig, p)) { dkim_error(dkim, "signature-key hash mismatch"); sig->sig_error = DKIM_SIGERROR_KEYHASHMISMATCH; return DKIM_STAT_CANTVRFY; } /* make sure it's a key designated for e-mail */ if (!dkim_key_smtp(set)) { dkim_error(dkim, "key type mismatch"); sig->sig_error = DKIM_SIGERROR_NOTEMAILKEY; return DKIM_STAT_CANTVRFY; } /* then key type */ p = dkim_param_get(set, (u_char *) "k"); if (p == NULL) { dkim_error(dkim, "key type missing"); sig->sig_error = DKIM_SIGERROR_KEYTYPEMISSING; return DKIM_STAT_SYNTAX; } else if (dkim_name_to_code(keytypes, (char *) p) == -1) { dkim_error(dkim, "unknown key type '%s'", p); sig->sig_error = DKIM_SIGERROR_KEYTYPEUNKNOWN; return DKIM_STAT_SYNTAX; } if (!gotkey) { /* decode the key */ sig->sig_b64key = dkim_param_get(set, (u_char *) "p"); if (sig->sig_b64key == NULL) { dkim_error(dkim, "key missing"); return DKIM_STAT_SYNTAX; } else if (sig->sig_b64key[0] == '\0') { return DKIM_STAT_REVOKED; } sig->sig_b64keylen = strlen((char *) sig->sig_b64key); sig->sig_key = DKIM_MALLOC(dkim, sig->sig_b64keylen); if (sig->sig_key == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sig->sig_b64keylen); return DKIM_STAT_NORESOURCE; } status = dkim_base64_decode(sig->sig_b64key, sig->sig_key, sig->sig_b64keylen); if (status < 0) { dkim_error(dkim, "key missing"); return DKIM_STAT_SYNTAX; } sig->sig_keylen = status; } /* store key flags */ p = dkim_param_get(set, (u_char *) "t"); if (p != NULL) { u_int flag; char *t; char *last; char tmp[BUFRSZ + 1]; strlcpy(tmp, (char *) p, sizeof tmp); for (t = strtok_r(tmp, ":", &last); t != NULL; t = strtok_r(NULL, ":", &last)) { flag = (u_int) dkim_name_to_code(keyflags, t); if (flag != (u_int) -1) sig->sig_flags |= flag; } } return DKIM_STAT_OK; } /* ** DKIM_HEADERCHECK -- check header validity ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** TRUE iff the header meets sanity checks. */ static _Bool dkim_headercheck(DKIM *dkim) { struct dkim_header *hdr; assert(dkim != NULL); if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_STRICTHDRS) != 0) { int status; unsigned char *user; unsigned char *domain; unsigned char *tmp; /* Date (must be exactly one) */ hdr = dkim_get_header(dkim, "Date", 4, 0); if (hdr == NULL) { dkim_error(dkim, "Date: header field absent"); return FALSE; } hdr = dkim_get_header(dkim, "Date", 4, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Date: header fields present"); return FALSE; } /* From (must be exactly one) */ hdr = dkim_get_header(dkim, "From", 4, 1); if (hdr != NULL) { dkim_error(dkim, "multiple From: header fields present"); return FALSE; } hdr = dkim_get_header(dkim, "From", 4, 0); if (hdr == NULL) { dkim_error(dkim, "From: header field absent"); return FALSE; } /* confirm it's parsable */ tmp = strdup(hdr->hdr_colon + 1); if (tmp != NULL) { status = dkim_mail_parse(tmp, &user, &domain); if (status != 0 || user == NULL || user[0] == '\0' || domain == NULL || domain[0] == '\0') { dkim_error(dkim, "From: header field cannot be parsed"); return FALSE; } free(tmp); } /* Sender (no more than one) */ hdr = dkim_get_header(dkim, "Sender", 6, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Sender: header fields present"); return FALSE; } /* Reply-To (no more than one) */ hdr = dkim_get_header(dkim, "Reply-To", 8, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Reply-To: header fields present"); return FALSE; } /* To (no more than one) */ hdr = dkim_get_header(dkim, "To", 2, 1); if (hdr != NULL) { dkim_error(dkim, "multiple To: header fields present"); return FALSE; } /* Cc (no more than one) */ hdr = dkim_get_header(dkim, "Cc", 2, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Cc: header fields present"); return FALSE; } /* Bcc (should we even bother?) */ hdr = dkim_get_header(dkim, "Bcc", 3, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Bcc: header fields present"); return FALSE; } /* Message-ID (no more than one) */ hdr = dkim_get_header(dkim, "Message-ID", 10, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Message-ID: header fields present"); return FALSE; } /* In-Reply-To (no more than one) */ hdr = dkim_get_header(dkim, "In-Reply-To", 11, 1); if (hdr != NULL) { dkim_error(dkim, "multiple In-Reply-To: header fields present"); return FALSE; } /* References (no more than one) */ hdr = dkim_get_header(dkim, "References", 10, 1); if (hdr != NULL) { dkim_error(dkim, "multiple References: header fields present"); return FALSE; } /* Subject (no more than one) */ hdr = dkim_get_header(dkim, "Subject", 7, 1); if (hdr != NULL) { dkim_error(dkim, "multiple Subject: header fields present"); return FALSE; } } return TRUE; } /* ** DKIM_EOH_SIGN -- declare end-of-headers; prepare for signing ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ static DKIM_STAT dkim_eoh_sign(DKIM *dkim) { _Bool keep; _Bool tmp; u_char *hn = NULL; DKIM_STAT status; int hashtype = DKIM_HASHTYPE_UNKNOWN; DKIM_CANON *bc; DKIM_CANON *hc; DKIM_LIB *lib; assert(dkim != NULL); #ifdef _FFR_RESIGN if (dkim->dkim_resign != NULL && dkim->dkim_hdrbind) return DKIM_STAT_INVALID; #endif /* _FFR_RESIGN */ if (dkim->dkim_state >= DKIM_STATE_EOH2) return DKIM_STAT_INVALID; if (dkim->dkim_state < DKIM_STATE_EOH2) dkim->dkim_state = DKIM_STATE_EOH2; lib = dkim->dkim_libhandle; assert(lib != NULL); tmp = ((lib->dkiml_flags & DKIM_LIBFLAGS_TMPFILES) != 0); keep = ((lib->dkiml_flags & DKIM_LIBFLAGS_KEEPFILES) != 0); dkim->dkim_version = lib->dkiml_version; /* check for header validity */ if (!dkim_headercheck(dkim)) { dkim->dkim_state = DKIM_STATE_UNUSABLE; return DKIM_STAT_SYNTAX; } /* ** Verify that all the required headers are present and ** marked for signing. */ hn = (u_char *) dkim_check_requiredhdrs(dkim); if (hn != NULL) { dkim_error(dkim, "required header \"%s\" not found", hn); dkim->dkim_state = DKIM_STATE_UNUSABLE; return DKIM_STAT_SYNTAX; } /* determine hash type */ switch (dkim->dkim_signalg) { case DKIM_SIGN_RSASHA1: hashtype = DKIM_HASHTYPE_SHA1; break; case DKIM_SIGN_RSASHA256: case DKIM_SIGN_ED25519SHA256: hashtype = DKIM_HASHTYPE_SHA256; break; default: assert(0); /* NOTREACHED */ } if (dkim->dkim_siglist == NULL) { /* initialize signature and canonicalization for signing */ dkim->dkim_siglist = DKIM_MALLOC(dkim, sizeof(DKIM_SIGINFO **)); if (dkim->dkim_siglist == NULL) { dkim_error(dkim, "failed to allocate %d byte(s)", sizeof(DKIM_SIGINFO *)); return DKIM_STAT_NORESOURCE; } dkim->dkim_siglist[0] = DKIM_MALLOC(dkim, sizeof(struct dkim_siginfo)); if (dkim->dkim_siglist[0] == NULL) { dkim_error(dkim, "failed to allocate %d byte(s)", sizeof(struct dkim_siginfo)); return DKIM_STAT_NORESOURCE; } dkim->dkim_sigcount = 1; memset(dkim->dkim_siglist[0], '\0', sizeof(struct dkim_siginfo)); dkim->dkim_siglist[0]->sig_domain = dkim->dkim_domain; dkim->dkim_siglist[0]->sig_selector = dkim->dkim_selector; dkim->dkim_siglist[0]->sig_hashtype = hashtype; dkim->dkim_siglist[0]->sig_signalg = dkim->dkim_signalg; status = dkim_add_canon(dkim, TRUE, dkim->dkim_hdrcanonalg, hashtype, NULL, NULL, 0, &hc); if (status != DKIM_STAT_OK) return status; status = dkim_add_canon(dkim, FALSE, dkim->dkim_bodycanonalg, hashtype, NULL, NULL, dkim->dkim_signlen, &bc); if (status != DKIM_STAT_OK) return status; dkim->dkim_siglist[0]->sig_hdrcanon = hc; dkim->dkim_siglist[0]->sig_hdrcanonalg = dkim->dkim_hdrcanonalg; dkim->dkim_siglist[0]->sig_bodycanon = bc; dkim->dkim_siglist[0]->sig_bodycanonalg = dkim->dkim_bodycanonalg; if (dkim->dkim_libhandle->dkiml_fixedtime != 0) { dkim->dkim_siglist[0]->sig_timestamp = dkim->dkim_libhandle->dkiml_fixedtime; } else { time_t now; (void) time(&now); dkim->dkim_siglist[0]->sig_timestamp = (uint64_t) now; } } /* initialize all canonicalizations */ status = dkim_canon_init(dkim, tmp, keep); if (status != DKIM_STAT_OK) return status; /* run the headers */ status = dkim_canon_runheaders(dkim); if (status != DKIM_STAT_OK) return status; return DKIM_STAT_OK; } /* ** DKIM_EOH_VERIFY -- declare end-of-headers; set up verification ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ static DKIM_STAT dkim_eoh_verify(DKIM *dkim) { _Bool keep; _Bool tmp; _Bool bsh; DKIM_STAT status; int c; DKIM_LIB *lib; DKIM_SET *set; assert(dkim != NULL); if (dkim->dkim_state >= DKIM_STATE_EOH2) return DKIM_STAT_INVALID; if (dkim->dkim_state < DKIM_STATE_EOH1) dkim->dkim_state = DKIM_STATE_EOH1; lib = dkim->dkim_libhandle; assert(lib != NULL); bsh = ((lib->dkiml_flags & DKIM_LIBFLAGS_BADSIGHANDLES) != 0); tmp = ((lib->dkiml_flags & DKIM_LIBFLAGS_TMPFILES) != 0); keep = ((lib->dkiml_flags & DKIM_LIBFLAGS_KEEPFILES) != 0); /* populate some stuff like dkim_sender, dkim_domain, dkim_user */ status = dkim_getsender(dkim); if (status != DKIM_STAT_OK && !bsh) { dkim->dkim_state = DKIM_STATE_UNUSABLE; return status; } /* check for header validity */ if (!dkim_headercheck(dkim)) { dkim->dkim_state = DKIM_STATE_UNUSABLE; return DKIM_STAT_SYNTAX; } /* allocate the siginfo array if not already done */ if (dkim->dkim_siglist == NULL) { /* count the signatures */ for (set = dkim_set_first(dkim, DKIM_SETTYPE_SIGNATURE); set != NULL; set = dkim_set_next(set, DKIM_SETTYPE_SIGNATURE)) { if (!set->set_bad || bsh) dkim->dkim_sigcount++; } /* if no signatures, return such */ if (dkim->dkim_sigcount == 0) { dkim->dkim_skipbody = TRUE; return DKIM_STAT_NOSIG; } status = dkim_siglist_setup(dkim); if (status != DKIM_STAT_OK) return status; /* initialize all discovered canonicalizations */ status = dkim_canon_init(dkim, tmp, keep); if (status != DKIM_STAT_OK) return status; } /* call the prescreen callback, if defined */ if (lib->dkiml_prescreen != NULL && !dkim->dkim_eoh_reentry) { status = lib->dkiml_prescreen(dkim, dkim->dkim_siglist, dkim->dkim_sigcount); switch (status) { case DKIM_CBSTAT_CONTINUE: case DKIM_CBSTAT_DEFAULT: break; case DKIM_CBSTAT_REJECT: return DKIM_STAT_CBREJECT; case DKIM_CBSTAT_TRYAGAIN: return DKIM_STAT_CBTRYAGAIN; case DKIM_CBSTAT_ERROR: return DKIM_STAT_CBERROR; default: return DKIM_STAT_CBINVALID; } } /* if set to ignore everything, treat message as unsigned */ set = NULL; for (c = 0; c < dkim->dkim_sigcount; c++) { if (!(dkim->dkim_siglist[c]->sig_flags & DKIM_SIGFLAG_IGNORE)) { set = dkim->dkim_siglist[c]->sig_taglist; break; } } if (set == NULL) { dkim->dkim_skipbody = TRUE; dkim->dkim_state = DKIM_STATE_EOH2; return DKIM_STAT_NOSIG; } /* run the headers */ if (!dkim->dkim_eoh_reentry) { status = dkim_canon_runheaders(dkim); if (status != DKIM_STAT_OK) return status; } /* do public key verification of all still-enabled signatures here */ if ((lib->dkiml_flags & DKIM_LIBFLAGS_DELAYSIGPROC) == 0) { for (c = 0; c < dkim->dkim_sigcount; c++) { if (!(dkim->dkim_siglist[c]->sig_flags & DKIM_SIGFLAG_PROCESSED) && !(dkim->dkim_siglist[c]->sig_flags & DKIM_SIGFLAG_IGNORE) && dkim->dkim_siglist[c]->sig_error == DKIM_SIGERROR_UNKNOWN) { status = dkim_sig_process(dkim, dkim->dkim_siglist[c]); if (status != DKIM_STAT_OK) { if (status == DKIM_STAT_CBTRYAGAIN) dkim->dkim_eoh_reentry = TRUE; return status; } } } } /* no re-entries beyond this point */ dkim->dkim_state = DKIM_STATE_EOH2; /* ** Possible short-circuit here if all signatures are: ** - marked to be ignored ** - definitely invalid ** - verification attempted but failed */ if ((lib->dkiml_flags & DKIM_LIBFLAGS_EOHCHECK) != 0) { _Bool good = FALSE; DKIM_SIGINFO *sig; for (c = 0; c < dkim->dkim_sigcount; c++) { sig = dkim->dkim_siglist[c]; /* ignored? */ if ((sig->sig_flags & DKIM_SIGFLAG_IGNORE) != 0) continue; /* had a processing error? */ if (sig->sig_error != DKIM_SIGERROR_UNKNOWN && sig->sig_error != DKIM_SIGERROR_OK) continue; /* processed but didn't pass? */ if ((sig->sig_flags & DKIM_SIGFLAG_PROCESSED) != 0 && (sig->sig_flags & DKIM_SIGFLAG_PASSED) == 0) continue; /* OK we had a good one */ good = TRUE; break; } /* no good ones */ if (!good) { /* report error on the last one */ if (sig->sig_error != DKIM_SIGERROR_UNKNOWN && sig->sig_error != DKIM_SIGERROR_OK) { dkim_error(dkim, dkim_code_to_name(sigerrors, sig->sig_error)); } return DKIM_STAT_CANTVRFY; } } return DKIM_STAT_OK; } /* ** DKIM_EOM_SIGN -- declare end-of-body; complete signing ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ static DKIM_STAT dkim_eom_sign(DKIM *dkim) { int status; size_t l = 0; size_t diglen; size_t siglen = 0; size_t len; DKIM_STAT ret; u_char *digest; u_char *sighdr; u_char *signature = NULL; DKIM_SIGINFO *sig; DKIM_CANON *hc; struct dkim_dstring *tmphdr; struct dkim_crypto *crypto = NULL; struct dkim_header hdr; assert(dkim != NULL); #ifdef _FFR_RESIGN if (dkim->dkim_resign != NULL) { if (dkim->dkim_hdrbind) { if (dkim->dkim_state != DKIM_STATE_INIT || dkim->dkim_resign->dkim_state != DKIM_STATE_EOM2) return DKIM_STAT_INVALID; } else { if (dkim->dkim_state < DKIM_STATE_EOH1 || dkim->dkim_resign->dkim_state != DKIM_STATE_EOM2) return DKIM_STAT_INVALID; } } else if (dkim->dkim_state >= DKIM_STATE_EOM2 || dkim->dkim_state < DKIM_STATE_EOH1) { return DKIM_STAT_INVALID; } #else /* _FFR_RESIGN */ if (dkim->dkim_state >= DKIM_STATE_EOM2 || dkim->dkim_state < DKIM_STATE_EOH1) return DKIM_STAT_INVALID; #endif /* _FFR_RESIGN */ if (dkim->dkim_chunkstate != DKIM_CHUNKSTATE_INIT && dkim->dkim_chunkstate != DKIM_CHUNKSTATE_DONE) return DKIM_STAT_INVALID; if (dkim->dkim_state < DKIM_STATE_EOM2) dkim->dkim_state = DKIM_STATE_EOM2; #ifdef _FFR_RESIGN if (dkim->dkim_resign != NULL) { _Bool found = FALSE; int c; char *hn; /* ** Verify that all the required headers are present and ** marked for signing. */ hn = (u_char *) dkim_check_requiredhdrs(dkim); if (hn != NULL) { dkim_error(dkim, "required header \"%s\" not found", hn); dkim->dkim_state = DKIM_STATE_UNUSABLE; return DKIM_STAT_SYNTAX; } /* ** Fail if the verification handle didn't work. For a ** multiply-signed message, we only require one passing ** signature (for now). */ if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_STRICTRESIGN) != 0) { for (c = 0; c < dkim->dkim_resign->dkim_sigcount; c++) { sig = dkim->dkim_resign->dkim_siglist[c]; if ((sig->sig_flags & DKIM_SIGFLAG_PASSED) != 0 && sig->sig_bh == DKIM_SIGBH_MATCH) { found = TRUE; break; } } if (!found) return DKIM_STAT_CANTVRFY; } } #endif /* _FFR_RESIGN */ /* finalize body canonicalizations */ status = dkim_canon_closebody(dkim); if (status != DKIM_STAT_OK) return status; dkim->dkim_bodydone = TRUE; /* set signature timestamp */ if (dkim->dkim_libhandle->dkiml_fixedtime != 0) { dkim->dkim_timestamp = dkim->dkim_libhandle->dkiml_fixedtime; } else { time_t now; (void) time(&now); dkim->dkim_timestamp = (uint64_t) now; } /* sign with l= if requested */ if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_SIGNLEN) != 0) dkim->dkim_partial = TRUE; /* get signature and canonicalization handles */ assert(dkim->dkim_siglist != NULL); assert(dkim->dkim_siglist[0] != NULL); sig = dkim->dkim_siglist[0]; hc = sig->sig_hdrcanon; if (dkim->dkim_keydata == NULL) { if (dkim_privkey_load(dkim) != DKIM_STAT_OK) return DKIM_STAT_NORESOURCE; } crypto = dkim->dkim_keydata; #ifdef USE_GNUTLS if (crypto->crypto_privkey == NULL) #else /* USE_GNUTLS */ if (!(crypto->crypto_key != NULL || (sig->sig_signalg == DKIM_SIGN_ED25519SHA256 && crypto->crypto_pkey != NULL))) #endif /* USE_GNUTLS */ { dkim_error(dkim, "private key load failed"); return DKIM_STAT_NORESOURCE; } sig->sig_keybits = crypto->crypto_keysize; sig->sig_signature = dkim->dkim_keydata; sig->sig_flags |= DKIM_SIGFLAG_KEYLOADED; if (sig->sig_signalg != DKIM_SIGN_ED25519SHA256 && sig->sig_keybits < dkim->dkim_libhandle->dkiml_minkeybits) { sig->sig_error = DKIM_SIGERROR_KEYTOOSMALL; dkim_error(dkim, "private key too small (%d bits, need at least %d)", sig->sig_keybits, dkim->dkim_libhandle->dkiml_minkeybits); return DKIM_STAT_SIGGEN; } switch (sig->sig_signalg) { case DKIM_SIGN_RSASHA1: case DKIM_SIGN_RSASHA256: { assert(sig->sig_hashtype == DKIM_HASHTYPE_SHA1 || sig->sig_hashtype == DKIM_HASHTYPE_SHA256); if (sig->sig_hashtype == DKIM_HASHTYPE_SHA256) { assert(dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256)); } sig->sig_signature = (void *) dkim->dkim_keydata; sig->sig_keytype = DKIM_KEYTYPE_RSA; break; } case DKIM_SIGN_ED25519SHA256: { assert(sig->sig_hashtype == DKIM_HASHTYPE_SHA256); sig->sig_signature = (void *) dkim->dkim_keydata; sig->sig_keytype = DKIM_KEYTYPE_ED25519; break; } default: assert(0); } /* construct the DKIM signature header to be canonicalized */ tmphdr = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (tmphdr == NULL) return DKIM_STAT_NORESOURCE; dkim_dstring_catn(tmphdr, (u_char *) DKIM_SIGNHEADER ": ", sizeof DKIM_SIGNHEADER + 1); ret = dkim_getsighdr_d(dkim, dkim_dstring_len(tmphdr), &sighdr, &len); if (ret != DKIM_STAT_OK) { dkim_dstring_free(tmphdr); return ret; } dkim_dstring_catn(tmphdr, sighdr, len); len = dkim_dstring_len(tmphdr); hdr.hdr_text = dkim_dstring_get(tmphdr); hdr.hdr_colon = hdr.hdr_text + DKIM_SIGNHEADER_LEN; hdr.hdr_namelen = DKIM_SIGNHEADER_LEN; hdr.hdr_textlen = len; hdr.hdr_flags = 0; hdr.hdr_next = NULL; /* canonicalize */ dkim_canon_signature(dkim, &hdr); dkim_dstring_free(tmphdr); /* finalize */ ret = dkim_canon_getfinal(hc, &digest, &diglen); if (ret != DKIM_STAT_OK) { dkim_error(dkim, "dkim_canon_getfinal() failed"); return DKIM_STAT_INTERNAL; } /* compute and store the signature */ switch (sig->sig_signalg) { #ifdef USE_GNUTLS case DKIM_SIGN_RSASHA1: case DKIM_SIGN_RSASHA256: { int alg; gnutls_datum_t dd; struct dkim_crypto *crypto; crypto = (struct dkim_crypto *) sig->sig_signature; dd.data = digest; dd.size = diglen; if (sig->sig_signalg == DKIM_SIGN_RSASHA1) alg = GNUTLS_DIG_SHA1; else alg = GNUTLS_DIG_SHA256; status = gnutls_privkey_sign_hash(crypto->crypto_privkey, alg, 0, &dd, &crypto->crypto_rsaout); if (status != GNUTLS_E_SUCCESS) { dkim_sig_load_ssl_errors(dkim, sig, status); dkim_error(dkim, "signature generation failed (status %d)", status); return DKIM_STAT_INTERNAL; } signature = crypto->crypto_rsaout.data; siglen = crypto->crypto_rsaout.size; break; } #else /* USE_GNUTLS */ case DKIM_SIGN_RSASHA1: case DKIM_SIGN_RSASHA256: { int nid; struct dkim_crypto *crypto; crypto = (struct dkim_crypto *) sig->sig_signature; nid = NID_sha1; if (dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256) && sig->sig_hashtype == DKIM_HASHTYPE_SHA256) nid = NID_sha256; status = RSA_sign(nid, digest, diglen, crypto->crypto_out, (int *) &l, crypto->crypto_key); if (status != 1 || l == 0) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "signature generation failed (status %d, length %d)", status, l); RSA_free(crypto->crypto_key); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_INTERNAL; } crypto->crypto_outlen = l; signature = crypto->crypto_out; siglen = crypto->crypto_outlen; break; } # ifdef HAVE_ED25519 case DKIM_SIGN_ED25519SHA256: { EVP_MD_CTX *md_ctx = NULL; struct dkim_crypto *crypto; crypto = (struct dkim_crypto *) sig->sig_signature; md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "failed to initialize digest context"); RSA_free(crypto->crypto_key); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_INTERNAL; } status = EVP_DigestSignInit(md_ctx, NULL, NULL, NULL, crypto->crypto_pkey); if (status == 1) { l = crypto->crypto_outlen; status = EVP_DigestSign(md_ctx, crypto->crypto_out, &l, digest, diglen); } if (status != 1) { /* dkim_load_ssl_errors(dkim, 0); */ dkim_error(dkim, "signature generation failed (status %d, length %d, %s)", status, l, ERR_error_string(ERR_get_error(), NULL)); RSA_free(crypto->crypto_key); BIO_CLOBBER(crypto->crypto_keydata); return DKIM_STAT_INTERNAL; } crypto->crypto_outlen = l; signature = crypto->crypto_out; siglen = crypto->crypto_outlen; EVP_MD_CTX_free(md_ctx); break; } # endif /* HAVE_ED25519 */ #endif /* USE_GNUTLS */ default: assert(0); } /* base64-encode the signature */ dkim->dkim_b64siglen = siglen * 3 + 5; dkim->dkim_b64siglen += (dkim->dkim_b64siglen / 60); dkim->dkim_b64sig = DKIM_MALLOC(dkim, dkim->dkim_b64siglen); if (dkim->dkim_b64sig == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", dkim->dkim_b64siglen); #ifndef USE_GNUTLS BIO_CLOBBER(crypto->crypto_keydata); #endif /* ! USE_GNUTLS */ return DKIM_STAT_NORESOURCE; } memset(dkim->dkim_b64sig, '\0', dkim->dkim_b64siglen); status = dkim_base64_encode(signature, siglen, dkim->dkim_b64sig, dkim->dkim_b64siglen); #ifndef USE_GNUTLS BIO_CLOBBER(crypto->crypto_keydata); #endif /* ! USE_GNUTLS */ if (status == -1) { dkim_error(dkim, "base64 encoding error (buffer too small)"); return DKIM_STAT_NORESOURCE; } dkim->dkim_signature = sig; return DKIM_STAT_OK; } /* ** DKIM_EOM_VERIFY -- declare end-of-body; complete verification ** ** Parameters: ** dkim -- DKIM handle ** testkey -- TRUE iff the a matching key was found but is marked as a ** test key (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ static DKIM_STAT dkim_eom_verify(DKIM *dkim, _Bool *testkey) { DKIM_STAT ret; int c; int status; DKIM_SIGINFO *sig = NULL; struct dkim_header *hdr; DKIM_LIB *lib; assert(dkim != NULL); if (dkim->dkim_state >= DKIM_STATE_EOM2 || dkim->dkim_state < DKIM_STATE_EOH1) return DKIM_STAT_INVALID; if (dkim->dkim_state < DKIM_STATE_EOM1) dkim->dkim_state = DKIM_STATE_EOM1; if (dkim->dkim_chunkstate != DKIM_CHUNKSTATE_INIT && dkim->dkim_chunkstate != DKIM_CHUNKSTATE_DONE) return DKIM_STAT_INVALID; /* finalize body canonicalizations */ ret = dkim_canon_closebody(dkim); if (ret != DKIM_STAT_OK) return ret; dkim->dkim_bodydone = TRUE; if (dkim->dkim_sigcount == 0) { /* unsigned */ if (dkim->dkim_domain == NULL) { u_char *domain; u_char *user; hdr = dkim_get_header(dkim, (u_char *) DKIM_FROMHEADER, DKIM_FROMHEADER_LEN, 0); if (hdr == NULL) { dkim_error(dkim, "no %s header found", DKIM_FROMHEADER); return DKIM_STAT_CANTVRFY; } if (hdr->hdr_colon == NULL) { dkim_error(dkim, "%s header malformed", DKIM_FROMHEADER); return DKIM_STAT_CANTVRFY; } status = dkim_mail_parse(hdr->hdr_colon + 1, &user, &domain); if (status != 0 || domain == NULL || domain[0] == '\0') { dkim_error(dkim, "%s header malformed", DKIM_FROMHEADER); return DKIM_STAT_CANTVRFY; } dkim->dkim_domain = dkim_strdup(dkim, domain, 0); if (dkim->dkim_domain == NULL) return DKIM_STAT_NORESOURCE; } dkim->dkim_state = DKIM_STATE_EOM2; return DKIM_STAT_NOSIG; } lib = dkim->dkim_libhandle; /* ** If a signature has "l=" set but it was greater than the ** canonicalized body length, the signature is invalid. */ for (c = 0; c < dkim->dkim_sigcount; c++) { sig = dkim->dkim_siglist[c]; if (sig->sig_bodycanon != NULL && sig->sig_bodycanon->canon_length != (ssize_t) -1 && sig->sig_bodycanon->canon_wrote < sig->sig_bodycanon->canon_length) sig->sig_error = DKIM_SIGERROR_TOOLARGE_L; } /* invoke the final callback if defined */ if (lib->dkiml_final != NULL) { status = lib->dkiml_final(dkim, dkim->dkim_siglist, dkim->dkim_sigcount); switch (status) { case DKIM_CBSTAT_CONTINUE: case DKIM_CBSTAT_DEFAULT: break; case DKIM_CBSTAT_REJECT: return DKIM_STAT_CBREJECT; case DKIM_CBSTAT_TRYAGAIN: return DKIM_STAT_CBTRYAGAIN; case DKIM_CBSTAT_ERROR: return DKIM_STAT_CBERROR; default: return DKIM_STAT_CBINVALID; } } dkim->dkim_state = DKIM_STATE_EOM2; /* see if we have a passing signature with bh match */ for (c = 0; c < dkim->dkim_sigcount; c++) { sig = dkim->dkim_siglist[c]; if ((sig->sig_flags & DKIM_SIGFLAG_PASSED) != 0 && (sig->sig_flags & DKIM_SIGFLAG_IGNORE) == 0 && sig->sig_bh == DKIM_SIGBH_MATCH) break; sig = NULL; } /* run 'em until we get one */ if (sig == NULL) { DKIM_SIGINFO *firstgood = NULL; for (c = 0; c < dkim->dkim_sigcount; c++) { sig = dkim->dkim_siglist[c]; /* if not ignoring */ if ((sig->sig_flags & DKIM_SIGFLAG_IGNORE) == 0) { /* run this signature */ status = dkim_sig_process(dkim, sig); if (status != DKIM_STAT_OK) { sig = NULL; continue; } /* ** If the signature has fewer than the ** minimum number of key bits required by ** configuration, the signature is invalid. */ if (sig->sig_error == 0 && sig->sig_signalg != DKIM_SIGN_ED25519SHA256 && sig->sig_keybits < lib->dkiml_minkeybits) { sig->sig_error = DKIM_SIGERROR_KEYTOOSMALL; sig->sig_flags &= ~DKIM_SIGFLAG_PASSED; } /* pass and bh match? */ if ((sig->sig_flags & DKIM_SIGFLAG_PASSED) != 0 && sig->sig_bh == DKIM_SIGBH_MATCH) { if (firstgood == NULL) firstgood = sig; /* continue? */ if ((lib->dkiml_flags & DKIM_LIBFLAGS_VERIFYONE) != 0) break; } } sig = NULL; } if (sig == NULL) sig = firstgood; } /* ** If still none, we're going to fail so just use the first one. */ if (sig == NULL) { for (c = 0; c < dkim->dkim_sigcount; c++) { sig = dkim->dkim_siglist[c]; if ((sig->sig_flags & DKIM_SIGFLAG_IGNORE) == 0) break; sig = NULL; } } /* caller marked everything with "ignore" */ if (sig == NULL) { dkim_error(dkim, "all signatures ignored by caller"); return DKIM_STAT_NOSIG; } dkim->dkim_signature = sig; /* things for which we return DKIM_STAT_CANTVRFY */ if (sig->sig_error != DKIM_SIGERROR_OK && sig->sig_error != DKIM_SIGERROR_UNKNOWN && sig->sig_error != DKIM_SIGERROR_KEYFAIL && sig->sig_error != DKIM_SIGERROR_BADSIG && sig->sig_error != DKIM_SIGERROR_KEYREVOKED && sig->sig_error != DKIM_SIGERROR_NOKEY) { if (dkim->dkim_error == NULL || dkim->dkim_error[0] == '\0') { dkim_error(dkim, dkim_code_to_name(sigerrors, sig->sig_error)); } return DKIM_STAT_CANTVRFY; } /* initialize final result */ ret = DKIM_STAT_OK; if (sig->sig_error == DKIM_SIGERROR_NOKEY) ret = DKIM_STAT_NOKEY; else if (sig->sig_error == DKIM_SIGERROR_KEYFAIL) ret = DKIM_STAT_KEYFAIL; else if (sig->sig_error == DKIM_SIGERROR_KEYREVOKED) ret = DKIM_STAT_REVOKED; else if ((sig->sig_flags & DKIM_SIGFLAG_PASSED) == 0) ret = DKIM_STAT_BADSIG; else if (sig->sig_bh == DKIM_SIGBH_MISMATCH) ret = DKIM_STAT_BADSIG; else if (sig->sig_error == DKIM_SIGERROR_BADSIG) ret = DKIM_STAT_BADSIG; /* set testkey based on the key flags */ if (testkey != NULL && (sig->sig_flags & DKIM_SIGFLAG_TESTKEY) != 0) *testkey = TRUE; return ret; } /* ** DKIM_NEW -- allocate a new message context ** ** Parameters: ** libhandle -- DKIM_LIB handle ** id -- transaction ID string ** memclosure -- memory closure ** hdrcanon_alg -- canonicalization algorithm to use for headers ** bodycanon_alg -- canonicalization algorithm to use for headers ** sign_alg -- signature algorithm to use ** statp -- status (returned) ** ** Return value: ** A new DKIM handle, or NULL on failure. */ static DKIM * dkim_new(DKIM_LIB *libhandle, const unsigned char *id, void *memclosure, dkim_canon_t hdrcanon_alg, dkim_canon_t bodycanon_alg, dkim_alg_t sign_alg, DKIM_STAT *statp) { DKIM *new; assert(libhandle != NULL); /* allocate the handle */ new = (DKIM *) dkim_malloc(libhandle, memclosure, sizeof(struct dkim)); if (new == NULL) { *statp = DKIM_STAT_NORESOURCE; return NULL; } /* populate defaults */ memset(new, '\0', sizeof(struct dkim)); new->dkim_id = id; new->dkim_signalg = (sign_alg == -1 ? DKIM_SIGN_DEFAULT : sign_alg); new->dkim_hdrcanonalg = (hdrcanon_alg == -1 ? DKIM_CANON_DEFAULT : hdrcanon_alg); new->dkim_bodycanonalg = (bodycanon_alg == -1 ? DKIM_CANON_DEFAULT : bodycanon_alg); new->dkim_querymethods = NULL; new->dkim_mode = DKIM_MODE_UNKNOWN; new->dkim_chunkcrlf = DKIM_CRLF_UNKNOWN; new->dkim_state = DKIM_STATE_INIT; new->dkim_margin = (size_t) DKIM_HDRMARGIN; new->dkim_closure = memclosure; new->dkim_libhandle = libhandle; new->dkim_tmpdir = libhandle->dkiml_tmpdir; new->dkim_timeout = libhandle->dkiml_timeout; *statp = DKIM_STAT_OK; #ifdef QUERY_CACHE if ((libhandle->dkiml_flags & DKIM_LIBFLAGS_CACHE) != 0 && libhandle->dkiml_cache == NULL) { int err = 0; libhandle->dkiml_cache = dkim_cache_init(&err, libhandle->dkiml_tmpdir); } #endif /* QUERY_CACHE */ return new; } #ifndef USE_GNUTLS /* ** DKIM_INIT_OPENSSL -- initialize OpenSSL algorithms if needed ** ** Parameters: ** None. ** ** Return value: ** None. */ static pthread_mutex_t openssl_lock = PTHREAD_MUTEX_INITIALIZER; static unsigned openssl_refcount = 0; static void dkim_init_openssl(void) { pthread_mutex_lock(&openssl_lock); if (openssl_refcount == 0) OpenSSL_add_all_algorithms(); openssl_refcount++; pthread_mutex_unlock(&openssl_lock); } /* ** DKIM_CLOSE_OPENSSL -- clean up OpenSSL algorithms if needed ** ** Parameters: ** None. ** ** Return value: ** None. */ static void dkim_close_openssl(void) { assert(openssl_refcount > 0); pthread_mutex_lock(&openssl_lock); openssl_refcount--; if (openssl_refcount == 0) EVP_cleanup(); pthread_mutex_unlock(&openssl_lock); } #endif /* ! USE_GNUTLS */ /* ========================= PUBLIC SECTION ========================== */ /* ** DKIM_INIT -- initialize a DKIM library context ** ** Parameters: ** caller_mallocf -- caller-provided memory allocation function ** caller_freef -- caller-provided memory release function ** ** Return value: ** A new DKIM_LIB handle suitable for use with other DKIM functions, or ** NULL on failure. ** ** Side effects: ** Crop circles near Birmingham. */ DKIM_LIB * dkim_init(void *(*caller_mallocf)(void *closure, size_t nbytes), void (*caller_freef)(void *closure, void *p)) { u_char *td; DKIM_LIB *libhandle; #ifndef USE_GNUTLS /* initialize OpenSSL algorithms */ dkim_init_openssl(); #endif /* USE_GNUTLS */ /* copy the parameters */ libhandle = (DKIM_LIB *) malloc(sizeof(struct dkim_lib)); if (libhandle == NULL) return NULL; td = (u_char *) getenv("DKIM_TMPDIR"); if (td == NULL || td[0] == '\0') td = (u_char *) DEFTMPDIR; libhandle->dkiml_signre = FALSE; libhandle->dkiml_skipre = FALSE; libhandle->dkiml_malloc = caller_mallocf; libhandle->dkiml_free = caller_freef; strlcpy((char *) libhandle->dkiml_tmpdir, (char *) td, sizeof libhandle->dkiml_tmpdir); libhandle->dkiml_flags = DKIM_LIBFLAGS_DEFAULT; libhandle->dkiml_timeout = DEFTIMEOUT; libhandle->dkiml_requiredhdrs = (u_char **) dkim_required_signhdrs; libhandle->dkiml_oversignhdrs = NULL; libhandle->dkiml_mbs = NULL; libhandle->dkiml_querymethod = DKIM_QUERY_UNKNOWN; memset(libhandle->dkiml_queryinfo, '\0', sizeof libhandle->dkiml_queryinfo); #ifdef QUERY_CACHE libhandle->dkiml_cache = NULL; #endif /* QUERY_CACHE */ libhandle->dkiml_fixedtime = 0; libhandle->dkiml_sigttl = 0; libhandle->dkiml_clockdrift = DEFCLOCKDRIFT; libhandle->dkiml_minkeybits = DEFMINKEYBITS; libhandle->dkiml_key_lookup = NULL; libhandle->dkiml_sig_handle = NULL; libhandle->dkiml_sig_handle_free = NULL; libhandle->dkiml_sig_tagvalues = NULL; libhandle->dkiml_prescreen = NULL; libhandle->dkiml_final = NULL; libhandle->dkiml_dns_callback = NULL; libhandle->dkiml_dns_service = NULL; libhandle->dkiml_dnsinit_done = FALSE; libhandle->dkiml_dns_init = dkim_res_init; libhandle->dkiml_dns_close = dkim_res_close; libhandle->dkiml_dns_start = dkim_res_query; libhandle->dkiml_dns_cancel = dkim_res_cancel; libhandle->dkiml_dns_waitreply = dkim_res_waitreply; #define FEATURE_INDEX(x) ((x) / (8 * sizeof(u_int))) #define FEATURE_OFFSET(x) ((x) % (8 * sizeof(u_int))) #define FEATURE_ADD(lib,x) (lib)->dkiml_flist[FEATURE_INDEX((x))] |= (1 << FEATURE_OFFSET(x)) libhandle->dkiml_flsize = (FEATURE_INDEX(DKIM_FEATURE_MAX)) + 1; libhandle->dkiml_flist = (u_int *) malloc(sizeof(u_int) * libhandle->dkiml_flsize); if (libhandle->dkiml_flist == NULL) { free(libhandle); return NULL; } memset(libhandle->dkiml_flist, '\0', sizeof(u_int) * libhandle->dkiml_flsize); #ifdef _FFR_DIFFHEADERS FEATURE_ADD(libhandle, DKIM_FEATURE_DIFFHEADERS); #endif /* _FFR_DIFFHEADERS */ #ifdef QUERY_CACHE FEATURE_ADD(libhandle, DKIM_FEATURE_QUERY_CACHE); #endif /* QUERY_CACHE */ #ifdef HAVE_SHA256 FEATURE_ADD(libhandle, DKIM_FEATURE_SHA256); #endif /* HAVE_SHA256 */ #ifdef HAVE_ED25519 FEATURE_ADD(libhandle, DKIM_FEATURE_ED25519); #endif /* HAVE_ED25519 */ #ifdef _FFR_DNSSEC FEATURE_ADD(libhandle, DKIM_FEATURE_DNSSEC); #endif /* _FFR_DNSSEC */ #ifdef _FFR_RESIGN FEATURE_ADD(libhandle, DKIM_FEATURE_RESIGN); #endif /* _FFR_RESIGN */ #ifdef _FFR_ATPS FEATURE_ADD(libhandle, DKIM_FEATURE_ATPS); #endif /* _FFR_ATPS */ FEATURE_ADD(libhandle, DKIM_FEATURE_OVERSIGN); FEATURE_ADD(libhandle, DKIM_FEATURE_XTAGS); #ifdef _FFR_CONDITIONAL FEATURE_ADD(libhandle, DKIM_FEATURE_CONDITIONAL); #endif /* _FFR_CONDITIONAL */ /* initialize the resolver */ (void) res_init(); return libhandle; } /* ** DKIM_CLOSE -- shut down a DKIM library package ** ** Parameters: ** lib -- library handle to shut down ** ** Return value: ** None. */ void dkim_close(DKIM_LIB *lib) { assert(lib != NULL); #ifdef QUERY_CACHE if (lib->dkiml_cache != NULL) (void) dkim_cache_close(lib->dkiml_cache); #endif /* QUERY_CACHE */ if (lib->dkiml_skipre) (void) regfree(&lib->dkiml_skiphdrre); if (lib->dkiml_signre) (void) regfree(&lib->dkiml_hdrre); if (lib->dkiml_oversignhdrs != NULL) dkim_clobber_array((char **) lib->dkiml_oversignhdrs); if (lib->dkiml_requiredhdrs != (u_char **) dkim_required_signhdrs) dkim_clobber_array((char **) lib->dkiml_requiredhdrs); if (lib->dkiml_mbs != NULL) dkim_clobber_array((char **) lib->dkiml_mbs); free(lib->dkiml_flist); if (lib->dkiml_dns_close != NULL && lib->dkiml_dns_service != NULL) lib->dkiml_dns_close(lib->dkiml_dns_service); free((void *) lib); #ifndef USE_GNUTLS dkim_close_openssl(); #endif /* ! USE_GNUTLS */ } /* ** DKIM_ERROR -- log an error into a DKIM handle ** ** Parameters: ** dkim -- DKIM context in which this is performed ** format -- format to apply ** ... -- arguments ** ** Return value: ** None. */ void dkim_error(DKIM *dkim, const char *format, ...) { int flen; int saverr; u_char *new; va_list va; assert(dkim != NULL); assert(format != NULL); saverr = errno; if (dkim->dkim_error == NULL) { dkim->dkim_error = DKIM_MALLOC(dkim, DEFERRLEN); if (dkim->dkim_error == NULL) { errno = saverr; return; } dkim->dkim_errlen = DEFERRLEN; } for (;;) { va_start(va, format); flen = vsnprintf((char *) dkim->dkim_error, dkim->dkim_errlen, format, va); va_end(va); /* compensate for broken vsnprintf() implementations */ if (flen == -1) flen = dkim->dkim_errlen * 2; if (flen >= dkim->dkim_errlen) { new = DKIM_MALLOC(dkim, flen + 1); if (new == NULL) { errno = saverr; return; } DKIM_FREE(dkim, dkim->dkim_error); dkim->dkim_error = new; dkim->dkim_errlen = flen + 1; } else { break; } } errno = saverr; } /* ** DKIM_OPTIONS -- get or set a library option ** ** Parameters: ** lib -- DKIM library handle ** op -- operation to perform ** opt -- option to get/set ** ptr -- pointer to its old/new value ** len -- memory available at "ptr" ** ** Return value: ** A DKIM_STAT constant. */ DKIM_STAT dkim_options(DKIM_LIB *lib, int op, dkim_opts_t opt, void *ptr, size_t len) { assert(lib != NULL); assert(op == DKIM_OP_SETOPT || op == DKIM_OP_GETOPT); assert(len != 0); switch (opt) { case DKIM_OPTS_TMPDIR: if (op == DKIM_OP_GETOPT) { strlcpy((char *) ptr, (char *) lib->dkiml_tmpdir, len); } else if (ptr == NULL) { strlcpy((char *) lib->dkiml_tmpdir, DEFTMPDIR, sizeof lib->dkiml_tmpdir); } else { strlcpy((char *) lib->dkiml_tmpdir, (char *) ptr, sizeof lib->dkiml_tmpdir); } return DKIM_STAT_OK; case DKIM_OPTS_FIXEDTIME: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_fixedtime) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_fixedtime, len); else memcpy(&lib->dkiml_fixedtime, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_MINKEYBITS: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_minkeybits) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_minkeybits, len); else memcpy(&lib->dkiml_minkeybits, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_SIGNATURETTL: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_sigttl) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_sigttl, len); else memcpy(&lib->dkiml_sigttl, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_CLOCKDRIFT: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_clockdrift) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_clockdrift, len); else memcpy(&lib->dkiml_clockdrift, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_FLAGS: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_flags) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_flags, len); else memcpy(&lib->dkiml_flags, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_TIMEOUT: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_timeout) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_timeout, len); else memcpy(&lib->dkiml_timeout, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_REQUIREDHDRS: if (len != sizeof lib->dkiml_requiredhdrs) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) { memcpy(ptr, &lib->dkiml_requiredhdrs, len); } else if (ptr == NULL) { if (lib->dkiml_requiredhdrs != (u_char **) dkim_required_signhdrs) dkim_clobber_array((char **) lib->dkiml_requiredhdrs); lib->dkiml_requiredhdrs = (u_char **) dkim_required_signhdrs; } else { const char **tmp; tmp = dkim_copy_array(ptr); if (tmp == NULL) return DKIM_STAT_NORESOURCE; if (lib->dkiml_requiredhdrs != (u_char **) dkim_required_signhdrs) dkim_clobber_array((char **) lib->dkiml_requiredhdrs); lib->dkiml_requiredhdrs = (u_char **) tmp; } return DKIM_STAT_OK; case DKIM_OPTS_OVERSIGNHDRS: if (len != sizeof lib->dkiml_oversignhdrs) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) { memcpy(ptr, &lib->dkiml_oversignhdrs, len); } else if (ptr == NULL) { if (lib->dkiml_oversignhdrs != NULL) dkim_clobber_array((char **) lib->dkiml_oversignhdrs); lib->dkiml_oversignhdrs = NULL; } else { const char **tmp; tmp = dkim_copy_array(ptr); if (tmp == NULL) return DKIM_STAT_NORESOURCE; if (lib->dkiml_oversignhdrs != NULL) dkim_clobber_array((char **) lib->dkiml_oversignhdrs); lib->dkiml_oversignhdrs = (u_char **) tmp; } return DKIM_STAT_OK; case DKIM_OPTS_MUSTBESIGNED: if (len != sizeof lib->dkiml_mbs) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) { memcpy(ptr, &lib->dkiml_mbs, len); } else if (ptr == NULL) { if (lib->dkiml_mbs != NULL) dkim_clobber_array((char **) lib->dkiml_mbs); lib->dkiml_mbs = NULL; } else { const char **tmp; tmp = dkim_copy_array(ptr); if (tmp == NULL) return DKIM_STAT_NORESOURCE; if (lib->dkiml_mbs != NULL) dkim_clobber_array((char **) lib->dkiml_mbs); lib->dkiml_mbs = (u_char **) tmp; } return DKIM_STAT_OK; case DKIM_OPTS_SIGNHDRS: if (len != sizeof(char **) || op == DKIM_OP_GETOPT) { return DKIM_STAT_INVALID; } else if (ptr == NULL) { if (lib->dkiml_signre) { (void) regfree(&lib->dkiml_hdrre); lib->dkiml_signre = FALSE; } } else { int status; u_char **hdrs; u_char **required_signhdrs; char buf[BUFRSZ + 1]; if (lib->dkiml_signre) { (void) regfree(&lib->dkiml_hdrre); lib->dkiml_signre = FALSE; } memset(buf, '\0', sizeof buf); hdrs = (u_char **) ptr; (void) strlcpy(buf, "^(", sizeof buf); required_signhdrs = lib->dkiml_requiredhdrs; if (!dkim_hdrlist((u_char *) buf, sizeof buf, (u_char **) required_signhdrs, TRUE)) return DKIM_STAT_INVALID; if (!dkim_hdrlist((u_char *) buf, sizeof buf, hdrs, FALSE)) return DKIM_STAT_INVALID; if (strlcat(buf, ")$", sizeof buf) >= sizeof buf) return DKIM_STAT_INVALID; status = regcomp(&lib->dkiml_hdrre, buf, (REG_EXTENDED|REG_ICASE)); if (status != 0) return DKIM_STAT_INTERNAL; lib->dkiml_signre = TRUE; } return DKIM_STAT_OK; case DKIM_OPTS_SKIPHDRS: if (len != sizeof(char **) || op == DKIM_OP_GETOPT) { return DKIM_STAT_INVALID; } else if (ptr == NULL) { if (lib->dkiml_skipre) { (void) regfree(&lib->dkiml_skiphdrre); lib->dkiml_skipre = FALSE; } } else { int status; u_char **hdrs; char buf[BUFRSZ + 1]; if (lib->dkiml_skipre) { (void) regfree(&lib->dkiml_skiphdrre); lib->dkiml_skipre = FALSE; } memset(buf, '\0', sizeof buf); hdrs = (u_char **) ptr; (void) strlcpy(buf, "^(", sizeof buf); if (!dkim_hdrlist((u_char *) buf, sizeof buf, hdrs, TRUE)) return DKIM_STAT_INVALID; if (strlcat(buf, ")$", sizeof buf) >= sizeof buf) return DKIM_STAT_INVALID; status = regcomp(&lib->dkiml_skiphdrre, buf, (REG_EXTENDED|REG_ICASE)); if (status != 0) return DKIM_STAT_INTERNAL; lib->dkiml_skipre = TRUE; } return DKIM_STAT_OK; case DKIM_OPTS_QUERYMETHOD: if (ptr == NULL) return DKIM_STAT_INVALID; if (len != sizeof lib->dkiml_querymethod) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) memcpy(ptr, &lib->dkiml_querymethod, len); else memcpy(&lib->dkiml_querymethod, ptr, len); return DKIM_STAT_OK; case DKIM_OPTS_QUERYINFO: if (ptr == NULL) return DKIM_STAT_INVALID; if (op == DKIM_OP_GETOPT) { strlcpy(ptr, (char *) lib->dkiml_queryinfo, len); } else { strlcpy((char *) lib->dkiml_queryinfo, ptr, sizeof lib->dkiml_queryinfo); } return DKIM_STAT_OK; default: return DKIM_STAT_INVALID; } } /* ** DKIM_FREE -- destroy a DKIM handle ** ** Parameters: ** dkim -- DKIM handle to destroy ** ** Return value: ** A DKIM_STAT constant. */ DKIM_STAT dkim_free(DKIM *dkim) { assert(dkim != NULL); #ifdef _FFR_RESIGN /* XXX -- this should be mutex-protected */ if (dkim->dkim_resign != NULL) { if (dkim->dkim_resign->dkim_refcnt == 0) dkim_free(dkim->dkim_resign); else dkim->dkim_resign->dkim_refcnt--; } else if (dkim->dkim_refcnt != 0) { return DKIM_STAT_INVALID; } #endif /* _FFR_RESIGN */ /* blast the headers */ #ifdef _FFR_RESIGN if (dkim->dkim_resign == NULL && dkim->dkim_hhead != NULL) #else /* _FFR_RESIGN */ if (dkim->dkim_hhead != NULL) #endif /* _FFR_RESIGN */ { struct dkim_header *next; struct dkim_header *hdr; for (hdr = dkim->dkim_hhead; hdr != NULL; ) { next = hdr->hdr_next; CLOBBER(hdr->hdr_text); CLOBBER(hdr); hdr = next; } } /* blast the data sets */ #ifdef _FFR_RESIGN if (dkim->dkim_resign == NULL && dkim->dkim_sethead != NULL) #else /* _FFR_RESIGN */ if (dkim->dkim_sethead != NULL) #endif /* _FFR_RESIGN */ { DKIM_SET *set; DKIM_SET *next; for (set = dkim->dkim_sethead; set != NULL; ) { next = set->set_next; dkim_set_free(dkim, set); set = next; } } /* trash the signature list */ if (dkim->dkim_siglist != NULL) { int c; for (c = 0; c < dkim->dkim_sigcount; c++) { if (dkim->dkim_siglist[c]->sig_context != NULL && dkim->dkim_libhandle->dkiml_sig_handle_free != NULL) { dkim->dkim_libhandle->dkiml_sig_handle_free(dkim->dkim_closure, dkim->dkim_siglist[c]->sig_context); } if (dkim->dkim_siglist[c]->sig_sslerrbuf != NULL) dkim_dstring_free(dkim->dkim_siglist[c]->sig_sslerrbuf); CLOBBER(dkim->dkim_siglist[c]->sig_key); CLOBBER(dkim->dkim_siglist[c]->sig_sig); if (dkim->dkim_siglist[c]->sig_keytype == DKIM_KEYTYPE_RSA) { struct dkim_crypto *crypto; crypto = dkim->dkim_siglist[c]->sig_signature; if (crypto != NULL) { #ifdef USE_GNUTLS KEY_CLOBBER(crypto->crypto_key); PUBKEY_CLOBBER(crypto->crypto_pubkey); PRIVKEY_CLOBBER(crypto->crypto_privkey); HCLOBBER(crypto->crypto_rsaout.data); #else /* USE_GNUTLS */ BIO_CLOBBER(crypto->crypto_keydata); EVP_CLOBBER(crypto->crypto_pkey); RSA_CLOBBER(crypto->crypto_key); CLOBBER(crypto->crypto_out); #endif /* USE_GNUTLS */ } } CLOBBER(dkim->dkim_siglist[c]->sig_signature); CLOBBER(dkim->dkim_siglist[c]); } CLOBBER(dkim->dkim_siglist); } if (dkim->dkim_querymethods != NULL) { struct dkim_qmethod *cur; struct dkim_qmethod *next; cur = dkim->dkim_querymethods; while (cur != NULL) { next = cur->qm_next; DKIM_FREE(dkim, cur->qm_type); if (cur->qm_options != NULL) DKIM_FREE(dkim, cur->qm_options); DKIM_FREE(dkim, cur); cur = next; } } if (dkim->dkim_xtags != NULL) { struct dkim_xtag *cur; struct dkim_xtag *next; cur = dkim->dkim_xtags; while (cur != NULL) { next = cur->xt_next; CLOBBER(cur->xt_tag); CLOBBER(cur->xt_value); free(cur); cur = next; } } if (dkim->dkim_hdrre != NULL) { regfree(dkim->dkim_hdrre); free(dkim->dkim_hdrre); } /* destroy canonicalizations */ dkim_canon_cleanup(dkim); CLOBBER(dkim->dkim_b64sig); CLOBBER(dkim->dkim_selector); CLOBBER(dkim->dkim_domain); CLOBBER(dkim->dkim_user); CLOBBER(dkim->dkim_key); CLOBBER(dkim->dkim_sender); CLOBBER(dkim->dkim_signer); CLOBBER(dkim->dkim_error); CLOBBER(dkim->dkim_zdecode); CLOBBER(dkim->dkim_hdrlist); DSTRING_CLOBBER(dkim->dkim_hdrbuf); DSTRING_CLOBBER(dkim->dkim_canonbuf); DSTRING_CLOBBER(dkim->dkim_sslerrbuf); dkim_mfree(dkim->dkim_libhandle, dkim->dkim_closure, dkim); return DKIM_STAT_OK; } /* ** DKIM_SIGN -- allocate a handle for use in a signature operation ** ** Parameters: ** libhandle -- DKIM_LIB handle ** id -- identification string (e.g. job ID) for logging ** memclosure -- memory closure for allocations (or NULL) ** secretkey -- secret key (PEM format) ** selector -- selector to be used when generating the signature header ** domain -- domain for which this message is being signed ** hdrcanonalg -- canonicalization algorithm to use for headers ** bodycanonalg -- canonicalization algorithm to use for body ** signalg -- signing algorithm to use ** length -- how many bytes of the body to sign (-1 for all) ** statp -- status (returned) ** ** Return value: ** A new signing handle, or NULL. */ DKIM * dkim_sign(DKIM_LIB *libhandle, const unsigned char *id, void *memclosure, const dkim_sigkey_t secretkey, const unsigned char *selector, const unsigned char *domain, dkim_canon_t hdrcanonalg, dkim_canon_t bodycanonalg, dkim_alg_t signalg, ssize_t length, DKIM_STAT *statp) { unsigned char *p; DKIM *new; assert(libhandle != NULL); assert(secretkey != NULL); assert(selector != NULL); assert(domain != NULL); assert(hdrcanonalg == DKIM_CANON_SIMPLE || hdrcanonalg == DKIM_CANON_RELAXED); assert(bodycanonalg == DKIM_CANON_SIMPLE || bodycanonalg == DKIM_CANON_RELAXED); assert(signalg == DKIM_SIGN_DEFAULT || signalg == DKIM_SIGN_RSASHA1 || signalg == DKIM_SIGN_RSASHA256 || signalg == DKIM_SIGN_ED25519SHA256); assert(statp != NULL); if (dkim_libfeature(libhandle, DKIM_FEATURE_SHA256)) { if (signalg == DKIM_SIGN_DEFAULT) signalg = DKIM_SIGN_RSASHA256; } else { if (signalg == DKIM_SIGN_RSASHA256) { *statp = DKIM_STAT_INVALID; return NULL; } if (signalg == DKIM_SIGN_DEFAULT) signalg = DKIM_SIGN_RSASHA1; } if (!dkim_strisprint((u_char *) domain) || !dkim_strisprint((u_char *) selector)) { *statp = DKIM_STAT_INVALID; return NULL; } new = dkim_new(libhandle, id, memclosure, hdrcanonalg, bodycanonalg, signalg, statp); if (new != NULL) { new->dkim_mode = DKIM_MODE_SIGN; /* do DER decoding here if needed */ if (strncmp((char *) secretkey, "MII", 3) == 0) { size_t b64len; b64len = strlen((char *) secretkey); new->dkim_key = (unsigned char *) DKIM_MALLOC(new, b64len); if (new->dkim_key == NULL) { *statp = DKIM_STAT_NORESOURCE; dkim_free(new); return NULL; } new->dkim_keylen = dkim_base64_decode(secretkey, new->dkim_key, b64len); if (new->dkim_keylen <= 0) { *statp = DKIM_STAT_NORESOURCE; dkim_free(new); return NULL; } } else { new->dkim_keylen = strlen((const char *) secretkey); new->dkim_key = dkim_strdup(new, secretkey, 0); if (new->dkim_key == NULL) { *statp = DKIM_STAT_NORESOURCE; dkim_free(new); return NULL; } } new->dkim_selector = dkim_strdup(new, selector, 0); new->dkim_domain = dkim_strdup(new, domain, 0); if (length == (ssize_t) -1) { new->dkim_signlen = ULONG_MAX; } else { new->dkim_signlen = length; new->dkim_partial = TRUE; } } return new; } /* ** DKIM_VERIFY -- allocate a handle for use in a verify operation ** ** Parameters: ** libhandle -- DKIM_LIB handle ** id -- identification string (e.g. job ID) for logging ** memclosure -- memory closure for allocations (or NULL) ** statp -- status (returned) ** ** Return value: ** A new signing handle, or NULL. */ DKIM * dkim_verify(DKIM_LIB *libhandle, const unsigned char *id, void *memclosure, DKIM_STAT *statp) { DKIM *new; assert(libhandle != NULL); assert(statp != NULL); new = dkim_new(libhandle, id, memclosure, DKIM_CANON_UNKNOWN, DKIM_CANON_UNKNOWN, DKIM_SIGN_UNKNOWN, statp); if (new != NULL) new->dkim_mode = DKIM_MODE_VERIFY; return new; } /* ** DKIM_RESIGN -- bind a new signing handle to a completed handle ** ** Parameters: ** new -- new signing handle ** old -- old signing/verifying handle ** hdrbind -- bind "new"'s header canonicalization to "old" as well ** as the body ** ** Return value: ** DKIM_STAT_OK -- success ** DKIM_STAT_INVALID -- invalid state of one or both handles ** ** Side effects: ** Sets up flags such that the two are bound; dkim_free() on "old" ** is now an invalid operation until "new" has been free'd. */ DKIM_STAT dkim_resign(DKIM *new, DKIM *old, _Bool hdrbind) { #ifdef _FFR_RESIGN _Bool keep; _Bool tmp; DKIM_STAT status; int hashtype = DKIM_HASHTYPE_UNKNOWN; DKIM_CANON *bc; DKIM_CANON *hc; DKIM_LIB *lib; assert(new != NULL); assert(old != NULL); if (new->dkim_mode != DKIM_MODE_SIGN || new->dkim_state != DKIM_STATE_INIT) return DKIM_STAT_INVALID; if (old->dkim_state >= DKIM_STATE_EOH1 || old->dkim_resign != NULL) return DKIM_STAT_INVALID; new->dkim_resign = old; new->dkim_hdrbind = hdrbind; /* XXX -- should be mutex-protected? */ old->dkim_refcnt++; if (new->dkim_hdrbind) { new->dkim_hhead = old->dkim_hhead; new->dkim_hdrcnt = old->dkim_hdrcnt; } lib = old->dkim_libhandle; assert(lib != NULL); tmp = ((lib->dkiml_flags & DKIM_LIBFLAGS_TMPFILES) != 0); keep = ((lib->dkiml_flags & DKIM_LIBFLAGS_KEEPFILES) != 0); new->dkim_version = lib->dkiml_version; /* determine hash type */ switch (new->dkim_signalg) { case DKIM_SIGN_RSASHA1: hashtype = DKIM_HASHTYPE_SHA1; break; case DKIM_SIGN_RSASHA256: hashtype = DKIM_HASHTYPE_SHA256; break; default: assert(0); /* NOTREACHED */ } /* initialize signature and canonicalization for signing */ new->dkim_siglist = DKIM_MALLOC(new, sizeof(DKIM_SIGINFO *)); if (new->dkim_siglist == NULL) { dkim_error(new, "failed to allocate %d byte(s)", sizeof(DKIM_SIGINFO *)); return DKIM_STAT_NORESOURCE; } new->dkim_siglist[0] = DKIM_MALLOC(new, sizeof(struct dkim_siginfo)); if (new->dkim_siglist[0] == NULL) { dkim_error(new, "failed to allocate %d byte(s)", sizeof(struct dkim_siginfo)); return DKIM_STAT_NORESOURCE; } new->dkim_sigcount = 1; memset(new->dkim_siglist[0], '\0', sizeof(struct dkim_siginfo)); new->dkim_siglist[0]->sig_domain = new->dkim_domain; new->dkim_siglist[0]->sig_selector = new->dkim_selector; new->dkim_siglist[0]->sig_hashtype = hashtype; new->dkim_siglist[0]->sig_signalg = new->dkim_signalg; status = dkim_add_canon(new, TRUE, new->dkim_hdrcanonalg, hashtype, NULL, NULL, 0, &hc); if (status != DKIM_STAT_OK) return status; status = dkim_add_canon(old, FALSE, new->dkim_bodycanonalg, hashtype, NULL, NULL, new->dkim_signlen, &bc); if (status != DKIM_STAT_OK) return status; new->dkim_siglist[0]->sig_hdrcanon = hc; new->dkim_siglist[0]->sig_hdrcanonalg = new->dkim_hdrcanonalg; new->dkim_siglist[0]->sig_bodycanon = bc; new->dkim_siglist[0]->sig_bodycanonalg = new->dkim_bodycanonalg; if (new->dkim_libhandle->dkiml_fixedtime != 0) { new->dkim_siglist[0]->sig_timestamp = new->dkim_libhandle->dkiml_fixedtime; } else { time_t now; (void) time(&now); new->dkim_siglist[0]->sig_timestamp = (uint64_t) now; } if (new->dkim_hdrbind) { _Bool keep; keep = ((lib->dkiml_flags & DKIM_LIBFLAGS_KEEPFILES) != 0); /* initialize all canonicalizations */ status = dkim_canon_init(new, tmp, keep); if (status != DKIM_STAT_OK) return status; /* run the headers */ status = dkim_canon_runheaders(new); if (status != DKIM_STAT_OK) return status; } return DKIM_STAT_OK; #else /* _FFR_RESIGN */ return DKIM_STAT_NOTIMPLEMENT; #endif /* _FFR_RESIGN */ } /* ** DKIM_SIG_PROCESS -- process a signature ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_process(DKIM *dkim, DKIM_SIGINFO *sig) { DKIM_STAT status; int nid; int vstat; size_t diglen = 0; #ifdef USE_GNUTLS gnutls_datum_t key; # if GNUTLS_VERSION_MAJOR == 3 gnutls_digest_algorithm_t hash; gnutls_sign_algorithm_t signalg; # endif /* GNUTLS_VERSION_MAJOR == 3 */ #else /* USE_GNUTLS */ BIO *key; #endif /* USE_GNUTLS */ u_char *digest = NULL; struct dkim_crypto *crypto; assert(dkim != NULL); assert(sig != NULL); /* skip it if we're supposed to ignore it */ if ((sig->sig_flags & DKIM_SIGFLAG_IGNORE) != 0) return DKIM_STAT_OK; /* skip it if there was a syntax or other error */ if (sig->sig_error != DKIM_SIGERROR_UNKNOWN) return DKIM_STAT_OK; #ifdef _FFR_CONDITIONAL /* error out if we're recursing into conditional signatures too much */ if (dkim->dkim_cddepth >= DKIM_MAXCDDEPTH) { dkim_error(dkim, "too many levels of conditional signature indirection"); sig->sig_error = DKIM_SIGERROR_CONDLOOP; return DKIM_STAT_CANTVRFY; } #endif /* _FFR_CONDITIONAL */ /* skip the DNS part if we've already done it */ if ((sig->sig_flags & DKIM_SIGFLAG_PROCESSED) == 0) { /* get the digest */ status = dkim_canon_getfinal(sig->sig_hdrcanon, &digest, &diglen); if (status != DKIM_STAT_OK) { dkim_error(dkim, "dkim_canon_getfinal() failed"); return DKIM_STAT_INTERNAL; } assert(digest != NULL && diglen != 0); /* retrieve the key */ status = dkim_get_key(dkim, sig, FALSE); if (status == DKIM_STAT_NOKEY) { sig->sig_flags |= DKIM_SIGFLAG_PROCESSED; sig->sig_error = DKIM_SIGERROR_NOKEY; return DKIM_STAT_OK; } else if (status == DKIM_STAT_KEYFAIL) { sig->sig_flags |= DKIM_SIGFLAG_PROCESSED; sig->sig_error = DKIM_SIGERROR_KEYFAIL; return DKIM_STAT_OK; } else if (status == DKIM_STAT_CANTVRFY || status == DKIM_STAT_SYNTAX) { sig->sig_flags |= DKIM_SIGFLAG_PROCESSED; if (sig->sig_error == DKIM_SIGERROR_UNKNOWN) sig->sig_error = DKIM_SIGERROR_DNSSYNTAX; return DKIM_STAT_OK; } else if (status == DKIM_STAT_MULTIDNSREPLY) { sig->sig_flags |= DKIM_SIGFLAG_PROCESSED; sig->sig_error = DKIM_SIGERROR_MULTIREPLY; return DKIM_STAT_OK; } else if (status == DKIM_STAT_REVOKED) { sig->sig_flags |= DKIM_SIGFLAG_PROCESSED; sig->sig_error = DKIM_SIGERROR_KEYREVOKED; return DKIM_STAT_OK; } else if (status != DKIM_STAT_OK) { return status; } #ifdef USE_GNUTLS key.data = sig->sig_key; key.size = sig->sig_keylen; #else /* USE_GNUTLS */ /* load the public key */ key = BIO_new_mem_buf(sig->sig_key, sig->sig_keylen); if (key == NULL) { dkim_error(dkim, "BIO_new_mem_buf() failed"); return DKIM_STAT_NORESOURCE; } #endif /* USE_GNUTLS */ /* set up to verify */ if (sig->sig_signature == NULL) { crypto = DKIM_MALLOC(dkim, sizeof(struct dkim_crypto)); if (crypto == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_crypto)); #ifndef USE_GNUTLS BIO_CLOBBER(key); #endif /* ! USE_GNUTLS */ return DKIM_STAT_NORESOURCE; } sig->sig_signature = crypto; } else { crypto = sig->sig_signature; } memset(crypto, '\0', sizeof(struct dkim_crypto)); #ifdef USE_GNUTLS crypto->crypto_sig.data = sig->sig_sig; crypto->crypto_sig.size = sig->sig_siglen; crypto->crypto_digest.data = digest; crypto->crypto_digest.size = diglen; status = gnutls_pubkey_init(&crypto->crypto_pubkey); if (status != GNUTLS_E_SUCCESS) { dkim_sig_load_ssl_errors(dkim, sig, status); dkim_error(dkim, "s=%s d=%s: gnutls_pubkey_init() failed", dkim_sig_getselector(sig), dkim_sig_getdomain(sig)); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } status = gnutls_pubkey_import(crypto->crypto_pubkey, &key, GNUTLS_X509_FMT_DER); if (status != GNUTLS_E_SUCCESS) { dkim_sig_load_ssl_errors(dkim, sig, status); dkim_error(dkim, "s=%s d=%s: gnutls_pubkey_import() failed", dkim_sig_getselector(sig), dkim_sig_getdomain(sig)); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } # if GNUTLS_VERSION_MAJOR == 2 vstat = gnutls_pubkey_verify_hash(crypto->crypto_pubkey, 0, &crypto->crypto_digest, &crypto->crypto_sig); # else /* GNUTLS_VERSION_MAJOR == 2 */ hash = dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256); hash = (hash && sig->sig_hashtype == DKIM_HASHTYPE_SHA256) ? GNUTLS_DIG_SHA256 : GNUTLS_DIG_SHA1; signalg = gnutls_pk_to_sign(GNUTLS_PK_RSA, hash); assert(signalg != GNUTLS_SIGN_UNKNOWN); vstat = gnutls_pubkey_verify_hash2(crypto->crypto_pubkey, signalg, 0, &crypto->crypto_digest, &crypto->crypto_sig); # endif /* GNUTLS_VERSION_MAJOR == 2 */ if (vstat < 0) dkim_sig_load_ssl_errors(dkim, sig, vstat); else /* RSA_verify() returns 1 on success */ vstat = 1; (void) gnutls_pubkey_get_pk_algorithm(crypto->crypto_pubkey, &crypto->crypto_keysize); sig->sig_keybits = crypto->crypto_keysize; #else /* USE_GNUTLS */ # ifdef HAVE_ED25519 if (sig->sig_signalg == DKIM_SIGN_ED25519SHA256) { char *keydata; long keylen; keylen = BIO_get_mem_data(key, &keydata); crypto->crypto_pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, keydata, keylen); } else # endif /* HAVE_ED25519 */ { crypto->crypto_pkey = d2i_PUBKEY_bio(key, NULL); } if (crypto->crypto_pkey == NULL) { dkim_sig_load_ssl_errors(dkim, sig, 0); dkim_error(dkim, "s=%s d=%s: EVP_PKEY construction failed", dkim_sig_getselector(sig), dkim_sig_getdomain(sig)); BIO_CLOBBER(key); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } /* set up the key object */ # ifdef HAVE_ED25519 if (sig->sig_signalg == DKIM_SIGN_ED25519SHA256) { EVP_MD_CTX *md_ctx; if (EVP_PKEY_id(crypto->crypto_pkey) != EVP_PKEY_ED25519) { dkim_error(dkim, "s=%s d=%s: not an ED25519 key", dkim_sig_getselector(sig), dkim_sig_getdomain(sig)); BIO_CLOBBER(key); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } crypto->crypto_in = sig->sig_sig; crypto->crypto_inlen = sig->sig_siglen; md_ctx = EVP_MD_CTX_new(); if (md_ctx == NULL) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "failed to initialize digest context"); BIO_CLOBBER(key); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } status = EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, crypto->crypto_pkey); if (status != 1) { dkim_load_ssl_errors(dkim, 0); dkim_error(dkim, "failed to initialize digest context"); BIO_CLOBBER(key); EVP_MD_CTX_free(md_ctx); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } vstat = EVP_DigestVerify(md_ctx, crypto->crypto_in, crypto->crypto_inlen, digest, diglen); EVP_MD_CTX_free(md_ctx); crypto->crypto_keysize = EVP_PKEY_size(crypto->crypto_pkey); } else # endif /* HAVE_ED25519 */ { crypto->crypto_key = EVP_PKEY_get1_RSA(crypto->crypto_pkey); if (crypto->crypto_key == NULL) { dkim_sig_load_ssl_errors(dkim, sig, 0); dkim_error(dkim, "s=%s d=%s: EVP_PKEY_get1_RSA() failed", dkim_sig_getselector(sig), dkim_sig_getdomain(sig)); BIO_CLOBBER(key); sig->sig_error = DKIM_SIGERROR_KEYDECODE; return DKIM_STAT_OK; } crypto->crypto_keysize = RSA_size(crypto->crypto_key); crypto->crypto_pad = RSA_PKCS1_PADDING; crypto->crypto_in = sig->sig_sig; crypto->crypto_inlen = sig->sig_siglen; sig->sig_keybits = 8 * crypto->crypto_keysize; nid = NID_sha1; if (dkim_libfeature(dkim->dkim_libhandle, DKIM_FEATURE_SHA256) && sig->sig_hashtype == DKIM_HASHTYPE_SHA256) nid = NID_sha256; vstat = RSA_verify(nid, digest, diglen, crypto->crypto_in, crypto->crypto_inlen, crypto->crypto_key); } dkim_sig_load_ssl_errors(dkim, sig, 0); BIO_CLOBBER(key); EVP_PKEY_free(crypto->crypto_pkey); crypto->crypto_pkey = NULL; if (crypto->crypto_key != NULL) { RSA_free(crypto->crypto_key); crypto->crypto_key = NULL; } #endif /* USE_GNUTLS */ if (vstat == 1) sig->sig_flags |= DKIM_SIGFLAG_PASSED; else sig->sig_error = DKIM_SIGERROR_BADSIG; sig->sig_flags |= DKIM_SIGFLAG_PROCESSED; } /* do the body hash check if possible */ if (dkim->dkim_bodydone && sig->sig_bh == DKIM_SIGBH_UNTESTED && (sig->sig_flags & DKIM_SIGFLAG_PASSED) != 0) { u_char *bhash; u_char b64buf[BUFRSZ]; memset(b64buf, '\0', sizeof b64buf); dkim_canon_getfinal(sig->sig_bodycanon, &digest, &diglen); bhash = dkim_param_get(sig->sig_taglist, (u_char *) "bh"); dkim_base64_encode(digest, diglen, b64buf, sizeof b64buf); if (strcmp((char *) bhash, (char *) b64buf) == 0) { sig->sig_bh = DKIM_SIGBH_MATCH; } else { sig->sig_error = DKIM_SIGERROR_BADSIG; sig->sig_bh = DKIM_SIGBH_MISMATCH; } } /* ** Fail if t=s was present in the key and the i= and d= domains ** don't match. */ if ((sig->sig_flags & DKIM_SIGFLAG_NOSUBDOMAIN) != 0) { char *d; char *i; d = (char *) dkim_param_get(sig->sig_taglist, (u_char *) "d"); i = (char *) dkim_param_get(sig->sig_taglist, (u_char *) "i"); if (i != NULL && d != NULL) { char *at; at = strchr(i, '@'); if (at == NULL) at = i; else at++; if (strcasecmp(at, d) != 0) sig->sig_error = DKIM_SIGERROR_SUBDOMAIN; } } /* ** Fail if the "must be signed" list was set and this signature didn't ** cover a must-be-signed header which was present. */ if (dkim->dkim_libhandle->dkiml_mbs != NULL) { int c; for (c = 0; dkim->dkim_libhandle->dkiml_mbs[c] != NULL; c++) { if (dkim_get_header(dkim, dkim->dkim_libhandle->dkiml_mbs[c], 0, 0) != NULL && !dkim_sig_hdrsigned(sig, dkim->dkim_libhandle->dkiml_mbs[c])) { sig->sig_error = DKIM_SIGERROR_MBSFAILED; break; } } } #ifdef _FFR_CONDITIONAL /* so far so good... */ if (sig->sig_error == DKIM_SIGERROR_UNKNOWN && sig->sig_bh != DKIM_SIGBH_UNTESTED) { /* recurse if this was a conditional signature */ if (sig->sig_bh == DKIM_SIGBH_MATCH) { char *cd; cd = (char *) dkim_param_get(sig->sig_taglist, (u_char *) "!cd"); if (cd != NULL) { _Bool found; int c; DKIM_SIGINFO *csig; /* find every match */ found = FALSE; for (c = 0; c < dkim->dkim_sigcount; c++) { csig = dkim->dkim_siglist[c]; if (strcasecmp(dkim_sig_getdomain(csig), cd) != 0) continue; if ((csig->sig_flags & DKIM_SIGFLAG_PROCESSED) == 0 || csig->sig_bh == DKIM_SIGBH_UNTESTED) { dkim->dkim_cddepth++; status = dkim_sig_process(dkim, csig); dkim->dkim_cddepth--; if (status != DKIM_STAT_OK) return status; } if (DKIM_SIG_CHECK(csig)) { found = TRUE; break; } } if (!found) sig->sig_error = DKIM_SIGERROR_CONDITIONAL; } } if (sig->sig_error == DKIM_SIGERROR_UNKNOWN) sig->sig_error = DKIM_SIGERROR_OK; } #else /* _FFR_CONDITIONAL */ if (sig->sig_error == DKIM_SIGERROR_UNKNOWN && sig->sig_bh != DKIM_SIGBH_UNTESTED) sig->sig_error = DKIM_SIGERROR_OK; #endif /* _FFR_CONDITIONAL */ return DKIM_STAT_OK; } /* ** DKIM_OHDRS -- extract and decode original headers ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** ptrs -- user-provided array of pointers to header strings (updated) ** pcnt -- number of pointers available (updated) ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** If the returned value of pcnt is greater that what it was originally, ** then there were more headers than there were pointers. */ DKIM_STAT dkim_ohdrs(DKIM *dkim, DKIM_SIGINFO *sig, u_char **ptrs, int *pcnt) { int n = 0; char *z; u_char *ch; u_char *p; u_char *q; char *last; assert(dkim != NULL); assert(ptrs != NULL); assert(pcnt != NULL); if (dkim->dkim_mode != DKIM_MODE_VERIFY) return DKIM_STAT_INVALID; /* pick the one we're going to use */ if (sig == NULL) { int c; for (c = 0; c < dkim->dkim_sigcount; c++) { sig = dkim->dkim_siglist[c]; if ((sig->sig_flags & DKIM_SIGFLAG_PROCESSED) != 0 && (sig->sig_flags & DKIM_SIGFLAG_IGNORE) == 0) break; sig = NULL; } } /* none useable; return error */ if (sig == NULL) return DKIM_STAT_INVALID; /* find the tag */ z = (char *) dkim_param_get(sig->sig_taglist, (u_char *) "z"); if (z == NULL || *z == '\0') { *pcnt = 0; return DKIM_STAT_OK; } /* get memory for the decode */ if (dkim->dkim_zdecode == NULL) { dkim->dkim_zdecode = DKIM_MALLOC(dkim, MAXHEADERS); if (dkim->dkim_zdecode == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", strlen(z)); return DKIM_STAT_NORESOURCE; } } /* copy it */ strlcpy((char *) dkim->dkim_zdecode, z, strlen(z)); /* decode */ for (ch = (u_char *) strtok_r(z, "|", &last); ch != NULL; ch = (u_char *) strtok_r(NULL, "|", &last)) { for (p = ch, q = ch; *p != '\0'; p++) { if (*p == '=') { char c; if (!isxdigit(*(p + 1)) || !isxdigit(*(p + 2))) { dkim_error(dkim, "invalid trailing character (0x%02x 0x%02x) in z= tag value", *(p + 1), *(p + 2)); return DKIM_STAT_INVALID; } c = 16 * dkim_hexchar(*(p + 1)) + dkim_hexchar(*(p + 2)); p += 2; *q = c; q++; } else { if (q != p) *q = *p; q++; } } *q = '\0'; if (n < *pcnt) ptrs[n] = ch; n++; } *pcnt = n; return DKIM_STAT_OK; } /* ** DKIM_DIFFHEADERS -- compare original headers with received headers ** ** Parameters: ** dkim -- DKIM handle ** canon -- header canonicalization mode in use ** maxcost -- maximum "cost" of changes to be reported ** ohdrs -- original headers, presumably extracted from a "z" tag ** nohdrs -- number of headers at "ohdrs" available ** out -- pointer to an array of struct dkim_hdrdiff objects (updated) ** nout -- counter of handles returned (updated) ** ** Return value: ** A DKIM_STAT_* constant. ** ** Side effects: ** A series of DKIM_HDRDIFF handles is allocated and must later be ** destroyed. */ DKIM_STAT dkim_diffheaders(DKIM *dkim, dkim_canon_t canon, int maxcost, char **ohdrs, int nohdrs, struct dkim_hdrdiff **out, int *nout) { #ifdef _FFR_DIFFHEADERS int n = 0; int a = 0; int c; int status; u_char *p; u_char *q; u_char *end; void *cls; struct dkim_header *hdr; struct dkim_hdrdiff *diffs = NULL; struct dkim_dstring *tmphdr; struct dkim_dstring **cohdrs; DKIM_LIB *lib; regaparams_t params; regamatch_t matches; regex_t re; u_char restr[BUFRSZ + 1]; assert(dkim != NULL); assert(out != NULL); assert(nout != NULL); if (dkim->dkim_mode != DKIM_MODE_VERIFY) return DKIM_STAT_INVALID; if (maxcost == 0) return DKIM_STAT_INVALID; tmphdr = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (tmphdr == NULL) { dkim_error(dkim, "failed to allocate dynamic string"); return DKIM_STAT_NORESOURCE; } lib = dkim->dkim_libhandle; cls = dkim->dkim_closure; memset(¶ms, '\0', sizeof params); params.cost_ins = COST_INSERT; params.cost_del = COST_DELETE; params.cost_subst = COST_SUBST; params.max_cost = maxcost; params.max_ins = DKIM_MAXHEADER; params.max_del = DKIM_MAXHEADER; params.max_subst = DKIM_MAXHEADER; params.max_err = maxcost; matches.nmatch = 0; matches.pmatch = NULL; /* canonicalize all the original header fields */ cohdrs = DKIM_MALLOC(dkim, sizeof(struct dkim_dstring *) * nohdrs); if (cohdrs == NULL) { dkim_error(dkim, strerror(errno)); return DKIM_STAT_NORESOURCE; } for (c = 0; c < nohdrs; c++) { cohdrs[c] = dkim_dstring_new(dkim, DKIM_MAXHEADER, 0); if (cohdrs[c] == NULL) { for (n = 0; n < c; n++) dkim_dstring_free(cohdrs[n]); DKIM_FREE(dkim, cohdrs); dkim_error(dkim, strerror(errno)); return DKIM_STAT_NORESOURCE; } status = dkim_canon_header_string(cohdrs[c], canon, ohdrs[c], strlen(ohdrs[c]), FALSE); if (status != DKIM_STAT_OK) { for (n = 0; n < c; n++) dkim_dstring_free(cohdrs[n]); DKIM_FREE(dkim, cohdrs); dkim_error(dkim, strerror(errno)); return status; } } for (hdr = dkim->dkim_hhead; hdr != NULL; hdr = hdr->hdr_next) { dkim_dstring_blank(tmphdr); status = dkim_canon_header_string(tmphdr, canon, hdr->hdr_text, hdr->hdr_textlen, FALSE); if (status != DKIM_STAT_OK) { dkim_dstring_free(tmphdr); for (c = 0; c < nohdrs; c++) dkim_dstring_free(cohdrs[c]); DKIM_FREE(dkim, cohdrs); return status; } memset(restr, '\0', sizeof restr); end = restr + sizeof restr; for (p = dkim_dstring_get(tmphdr), q = restr; *p != '\0' && q < end - 3; p++) { if (q == restr) *q++ = '^'; if (*p == '*' || *p == '\\' || *p == '$' || *p == '+' || *p == '[' || *p == ']' || *p == '(' || *p == ')' || *p == '.' || *p == '|') *q++ = '\\'; *q++ = *p; } *q = '$'; status = tre_regcomp(&re, restr, REG_NOSUB); if (status != 0) { char err[BUFRSZ + 1]; memset(err, '\0', sizeof err); (void) tre_regerror(status, &re, err, sizeof err); dkim_error(dkim, err); if (diffs != NULL) dkim_mfree(lib, cls, diffs); dkim_dstring_free(tmphdr); for (c = 0; c < nohdrs; c++) dkim_dstring_free(cohdrs[c]); DKIM_FREE(dkim, cohdrs); return DKIM_STAT_INTERNAL; } for (c = 0; c < nohdrs; c++) { /* not even the same header field */ if (hdr->hdr_namelen != hdr->hdr_textlen && strncmp(dkim_dstring_get(cohdrs[c]), dkim_dstring_get(tmphdr), hdr->hdr_namelen + 1) != 0) continue; /* same, no changes at all */ if (strcmp(dkim_dstring_get(cohdrs[c]), dkim_dstring_get(tmphdr)) == 0) continue; /* check for approximate match */ status = tre_regaexec(&re, dkim_dstring_get(cohdrs[c]), &matches, params, 0); if (status == 0) { if (n + 1 > a) { int sz; struct dkim_hdrdiff *new; if (a == 0) a = 16; else a *= 2; sz = a * sizeof(struct dkim_hdrdiff); new = (struct dkim_hdrdiff *) dkim_malloc(lib, cls, sz); if (new == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sz); if (diffs != NULL) { dkim_mfree(lib, cls, diffs); } dkim_dstring_free(tmphdr); for (c = 0; c < nohdrs; c++) dkim_dstring_free(cohdrs[c]); DKIM_FREE(dkim, cohdrs); return DKIM_STAT_NORESOURCE; } dkim_mfree(lib, cls, diffs); diffs = new; sz = (a - n) & sizeof(struct dkim_hdrdiff); memset(&diffs[n], '\0', sz); } diffs[n].hd_old = ohdrs[c]; diffs[n].hd_new = hdr->hdr_text; n++; } } tre_regfree(&re); } *out = diffs; *nout = n; dkim_dstring_free(tmphdr); for (c = 0; c < nohdrs; c++) dkim_dstring_free(cohdrs[c]); DKIM_FREE(dkim, cohdrs); return DKIM_STAT_OK; #else /* _FFR_DIFFHEADERS */ return DKIM_STAT_NOTIMPLEMENT; #endif /* _FFR_DIFFHEADERS */ } /* ** DKIM_HEADER -- process a header ** ** Parameters: ** dkim -- DKIM handle ** hdr -- header text ** len -- bytes available at "hdr" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_header(DKIM *dkim, u_char *hdr, size_t len) { u_char *colon; u_char *semicolon; u_char *end = NULL; size_t c; struct dkim_header *h; assert(dkim != NULL); assert(hdr != NULL); assert(len != 0); #ifdef _FFR_RESIGN if (dkim->dkim_hdrbind) return DKIM_STAT_INVALID; #endif /* _FFR_RESIGN */ if (dkim->dkim_state > DKIM_STATE_HEADER) return DKIM_STAT_INVALID; dkim->dkim_state = DKIM_STATE_HEADER; /* enforce RFC 5322, Section 2.2 */ colon = NULL; for (c = 0; c < len; c++) { if (colon == NULL) { /* ** Field names are printable ASCII; also tolerate ** plain whitespace. */ if (hdr[c] < 32 || hdr[c] > 126) return DKIM_STAT_SYNTAX; /* the colon is special */ if (hdr[c] == ':') colon = &hdr[c]; } else { /* field bodies are printable ASCII, SP, HT, CR, LF */ if (!(hdr[c] != 9 || /* HT */ hdr[c] != 10 || /* LF */ hdr[c] != 13 || /* CR */ (hdr[c] >= 32 && hdr[c] <= 126) /* SP, print */ )) return DKIM_STAT_SYNTAX; } } if (colon == NULL) return DKIM_STAT_SYNTAX; end = colon; while (end > hdr && isascii(*(end - 1)) && isspace(*(end - 1))) end--; /* don't allow a field name containing a semicolon */ semicolon = memchr(hdr, ';', len); if (semicolon != NULL && colon != NULL && semicolon < colon) return DKIM_STAT_SYNTAX; /* see if this is one we should skip */ if (dkim->dkim_mode == DKIM_MODE_SIGN && dkim->dkim_libhandle->dkiml_skipre) { int status; unsigned char name[DKIM_MAXHEADER + 1]; strlcpy((char *) name, (char *) hdr, sizeof name); if (end != NULL) name[end - hdr] = '\0'; status = regexec(&dkim->dkim_libhandle->dkiml_skiphdrre, (char *) name, 0, NULL, 0); if (status == 0) return DKIM_STAT_OK; else assert(status == REG_NOMATCH); } h = DKIM_MALLOC(dkim, sizeof(struct dkim_header)); if (h == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_header)); return DKIM_STAT_NORESOURCE; } if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF) != 0) { u_char prev = '\0'; u_char *p; u_char *q; struct dkim_dstring *tmphdr; tmphdr = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (tmphdr == NULL) { DKIM_FREE(dkim, h); return DKIM_STAT_NORESOURCE; } q = hdr + len; for (p = hdr; p < q && *p != '\0'; p++) { if (*p == '\n' && prev != '\r') /* bare LF */ { dkim_dstring_catn(tmphdr, CRLF, 2); } else if (prev == '\r' && *p != '\n') /* bare CR */ { dkim_dstring_cat1(tmphdr, '\n'); dkim_dstring_cat1(tmphdr, *p); } else /* other */ { dkim_dstring_cat1(tmphdr, *p); } prev = *p; } if (prev == '\r') /* end CR */ dkim_dstring_cat1(tmphdr, '\n'); h->hdr_text = dkim_strdup(dkim, dkim_dstring_get(tmphdr), dkim_dstring_len(tmphdr)); dkim_dstring_free(tmphdr); } else { h->hdr_text = dkim_strdup(dkim, hdr, len); } if (h->hdr_text == NULL) { DKIM_FREE(dkim, h); return DKIM_STAT_NORESOURCE; } h->hdr_namelen = end != NULL ? end - hdr : len; h->hdr_textlen = len; if (colon == NULL) h->hdr_colon = NULL; else h->hdr_colon = h->hdr_text + (colon - hdr); h->hdr_flags = 0; h->hdr_next = NULL; if (dkim->dkim_hhead == NULL) { dkim->dkim_hhead = h; dkim->dkim_htail = h; } else { dkim->dkim_htail->hdr_next = h; dkim->dkim_htail = h; } dkim->dkim_hdrcnt++; if (h->hdr_colon != NULL) { if (h->hdr_namelen == DKIM_SIGNHEADER_LEN && strncasecmp((char *) hdr, DKIM_SIGNHEADER, DKIM_SIGNHEADER_LEN) == 0) { DKIM_STAT status; size_t plen; plen = len - (h->hdr_colon - h->hdr_text) - 1; status = dkim_process_set(dkim, DKIM_SETTYPE_SIGNATURE, h->hdr_colon + 1, plen, h, FALSE, NULL); if (status != DKIM_STAT_OK) return status; } } return DKIM_STAT_OK; } /* ** DKIM_EOH -- declare end-of-headers ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_eoh(DKIM *dkim) { assert(dkim != NULL); if (dkim->dkim_mode == DKIM_MODE_VERIFY) return dkim_eoh_verify(dkim); else return dkim_eoh_sign(dkim); } /* ** DKIM_BODY -- pass a body chunk in for processing ** ** Parameters: ** dkim -- DKIM handle ** buf -- body chunk ** buflen -- number of bytes at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_body(DKIM *dkim, u_char *buf, size_t buflen) { assert(dkim != NULL); assert(buf != NULL); #ifdef _FFR_RESIGN if (dkim->dkim_resign != NULL) return DKIM_STAT_INVALID; #endif /* _FFR_RESIGN */ if (dkim->dkim_state > DKIM_STATE_BODY || dkim->dkim_state < DKIM_STATE_EOH1) return DKIM_STAT_INVALID; dkim->dkim_state = DKIM_STATE_BODY; if (dkim->dkim_skipbody) return DKIM_STAT_OK; return dkim_canon_bodychunk(dkim, buf, buflen); } /* ** DKIM_EOM -- declare end-of-body; conduct verification or signing ** ** Parameters: ** dkim -- DKIM handle ** testkey -- TRUE iff the a matching key was found but is marked as a ** test key (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_eom(DKIM *dkim, _Bool *testkey) { assert(dkim != NULL); if (dkim->dkim_mode == DKIM_MODE_SIGN) return dkim_eom_sign(dkim); else return dkim_eom_verify(dkim, testkey); } /* ** DKIM_CHUNK -- process a message chunk ** ** Parameters: ** dkim -- DKIM handle ** buf -- data to process ** buflen -- number of bytes at "buf" to process ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_chunk(DKIM *dkim, u_char *buf, size_t buflen) { _Bool bso; DKIM_STAT status; unsigned char *p; unsigned char *end; assert(dkim != NULL); bso = ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_BADSIGHANDLES) != 0); if ((dkim->dkim_libhandle->dkiml_flags & DKIM_LIBFLAGS_FIXCRLF) == 0) dkim->dkim_chunkcrlf = DKIM_CRLF_CRLF; /* verify chunking state */ if (dkim->dkim_chunkstate >= DKIM_CHUNKSTATE_DONE) { return DKIM_STAT_INVALID; } else if (dkim->dkim_chunkstate == DKIM_CHUNKSTATE_INIT) { if (dkim->dkim_hdrbuf == NULL) { dkim->dkim_hdrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (dkim->dkim_hdrbuf == NULL) return DKIM_STAT_NORESOURCE; } else { dkim_dstring_blank(dkim->dkim_hdrbuf); } dkim->dkim_chunkstate = DKIM_CHUNKSTATE_HEADER; dkim->dkim_chunksm = 0; } /* process an "end" call */ if (buf == NULL || buflen == 0) { if (dkim->dkim_chunkstate == DKIM_CHUNKSTATE_HEADER) { if (dkim_dstring_len(dkim->dkim_hdrbuf) > 0) { status = dkim_header(dkim, dkim_dstring_get(dkim->dkim_hdrbuf), dkim_dstring_len(dkim->dkim_hdrbuf)); if (status != DKIM_STAT_OK && !(status == DKIM_STAT_SYNTAX && bso)) return status; } status = dkim_eoh(dkim); if (status != DKIM_STAT_OK) return status; } dkim->dkim_chunkstate = DKIM_CHUNKSTATE_DONE; return DKIM_STAT_OK; } /* if we're in body state, just call dkim_body() */ if (dkim->dkim_chunkstate == DKIM_CHUNKSTATE_BODY) return dkim_body(dkim, buf, buflen); assert(dkim->dkim_chunkstate == DKIM_CHUNKSTATE_HEADER); end = buf + buflen - 1; /* process headers */ for (p = buf; p <= end; p++) { switch (dkim->dkim_chunksm) { case 0: if (*p == '\n' && dkim->dkim_chunkcrlf != DKIM_CRLF_CRLF) { dkim->dkim_chunkcrlf = DKIM_CRLF_LF; /* ** If this is a CRLF up front, change state ** and write the rest as part of the body. */ if (dkim->dkim_hhead == NULL && dkim_dstring_len(dkim->dkim_hdrbuf) == 2) { status = dkim_eoh(dkim); if (status != DKIM_STAT_OK) return status; dkim->dkim_chunkstate = DKIM_CHUNKSTATE_BODY; if (p < end) { return dkim_body(dkim, p + 1, end - p); } else { return DKIM_STAT_OK; } } dkim_dstring_catn(dkim->dkim_hdrbuf, CRLF, 2); dkim->dkim_chunksm = 2; } else { dkim_dstring_cat1(dkim->dkim_hdrbuf, *p); if (*p == '\r') dkim->dkim_chunksm = 1; } break; case 1: dkim_dstring_cat1(dkim->dkim_hdrbuf, *p); if (*p == '\n') { if (dkim->dkim_chunkcrlf == DKIM_CRLF_UNKNOWN) dkim->dkim_chunkcrlf = DKIM_CRLF_CRLF; /* ** If this is a CRLF up front, change state ** and write the rest as part of the body. */ if (dkim->dkim_hhead == NULL && dkim_dstring_len(dkim->dkim_hdrbuf) == 2) { status = dkim_eoh(dkim); if (status != DKIM_STAT_OK) return status; dkim->dkim_chunkstate = DKIM_CHUNKSTATE_BODY; if (p < end) { return dkim_body(dkim, p + 1, end - p); } else { return DKIM_STAT_OK; } } dkim->dkim_chunksm = 2; } else if (*p != '\r') { dkim->dkim_chunksm = 0; } break; case 2: if (DKIM_ISLWSP(*p)) { dkim_dstring_cat1(dkim->dkim_hdrbuf, *p); dkim->dkim_chunksm = 0; break; } else if (*p == '\r' && dkim->dkim_chunkcrlf == DKIM_CRLF_CRLF) { dkim->dkim_chunksm = 3; break; } else if (*p != '\n' || dkim->dkim_chunkcrlf != DKIM_CRLF_LF) { status = dkim_header(dkim, dkim_dstring_get(dkim->dkim_hdrbuf), dkim_dstring_len(dkim->dkim_hdrbuf) - 2); if (status != DKIM_STAT_OK && !(status == DKIM_STAT_SYNTAX && bso)) return status; dkim_dstring_blank(dkim->dkim_hdrbuf); dkim_dstring_cat1(dkim->dkim_hdrbuf, *p); dkim->dkim_chunksm = 0; break; } /* FALLTHROUGH */ case 3: if (*p == '\n') { if (dkim_dstring_len(dkim->dkim_hdrbuf) > 0) { status = dkim_header(dkim, dkim_dstring_get(dkim->dkim_hdrbuf), dkim_dstring_len(dkim->dkim_hdrbuf) - 2); if (status != DKIM_STAT_OK && !(status == DKIM_STAT_SYNTAX && bso)) return status; } status = dkim_eoh(dkim); if (status != DKIM_STAT_OK) return status; dkim->dkim_chunkstate = DKIM_CHUNKSTATE_BODY; if (p < end) return dkim_body(dkim, p + 1, end - p); else return DKIM_STAT_OK; } else { status = dkim_header(dkim, dkim_dstring_get(dkim->dkim_hdrbuf), dkim_dstring_len(dkim->dkim_hdrbuf) - 2); if (status != DKIM_STAT_OK && !(status == DKIM_STAT_SYNTAX && bso)) return status; dkim_dstring_blank(dkim->dkim_hdrbuf); dkim_dstring_cat1(dkim->dkim_hdrbuf, '\r'); dkim_dstring_cat1(dkim->dkim_hdrbuf, *p); dkim->dkim_chunksm = 0; } break; default: assert(0); /* NOTREACHED */ } } return DKIM_STAT_OK; } /* ** DKIM_MINBODY -- return number of bytes still expected ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** 0 -- all canonicalizations satisfied ** ULONG_MAX -- at least one canonicalization wants the whole message ** other -- bytes required to satisfy all canonicalizations */ u_long dkim_minbody(DKIM *dkim) { assert(dkim != NULL); return dkim_canon_minbody(dkim); } /* ** DKIM_KEY_SYNTAX -- process a key record parameter set for valid syntax ** ** Parameters: ** dkim -- DKIM context in which this is performed ** str -- string to be scanned ** len -- number of bytes available at "str" ** ** Return value: ** A DKIM_STAT constant. */ DKIM_STAT dkim_key_syntax(DKIM *dkim, u_char *str, size_t len) { return dkim_process_set(dkim, DKIM_SETTYPE_KEY, str, len, NULL, TRUE, NULL); } /* ** DKIM_SIG_SYNTAX -- process a signature parameter set for valid syntax ** ** Parameters: ** dkim -- DKIM context in which this is performed ** str -- string to be scanned ** len -- number of bytes available at "str" ** ** Return value: ** A DKIM_STAT constant. */ DKIM_STAT dkim_sig_syntax(DKIM *dkim, u_char *str, size_t len) { return dkim_process_set(dkim, DKIM_SETTYPE_SIGNATURE, str, len, NULL, TRUE, NULL); } /* ** DKIM_GETID -- retrieve "id" pointer from a handle ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** The "id" pointer from inside the handle, stored when it was created. */ const char * dkim_getid(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_id; } /* ** DKIM_GETSIGLIST -- retrieve the list of signatures ** ** Parameters: ** dkim -- DKIM handle ** sigs -- pointer to a vector of DKIM_SIGINFO pointers (updated) ** nsigs -- pointer to an integer to receive the pointer count (updated) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_getsiglist(DKIM *dkim, DKIM_SIGINFO ***sigs, int *nsigs) { assert(dkim != NULL); assert(sigs != NULL); assert(nsigs != NULL); if (dkim->dkim_state < DKIM_STATE_EOH2) return DKIM_STAT_INVALID; *sigs = dkim->dkim_siglist; *nsigs = dkim->dkim_sigcount; return DKIM_STAT_OK; } /* ** DKIM_GETSIGNATURE -- retrieve the "final" signature ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to a DKIM_SIGINFO handle which is the one libopendkim will ** use to return a "final" result; NULL if none could be determined. */ DKIM_SIGINFO * dkim_getsignature(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_signature; } /* ** DKIM_GETSIGHDR_D -- for signing operations, retrieve the complete signature ** header, doing so dynamically ** ** Parameters: ** dkim -- DKIM handle ** initial -- initial line width ** buf -- pointer to buffer containing the signature (returned) ** buflen -- number of bytes at "buf" (returned) ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** Per RFC6376 Section 3.7, the signature header returned here does ** not contain a trailing CRLF. */ DKIM_STAT dkim_getsighdr_d(DKIM *dkim, size_t initial, u_char **buf, size_t *buflen) { size_t len; char *ctx; char *pv; DKIM_SIGINFO *sig; struct dkim_dstring *tmpbuf; assert(dkim != NULL); assert(buf != NULL); assert(buflen != NULL); if (dkim->dkim_state != DKIM_STATE_EOM2 || dkim->dkim_mode != DKIM_MODE_SIGN) return DKIM_STAT_INVALID; #define DELIMITER "\001" sig = dkim->dkim_signature; if (sig == NULL) sig = dkim->dkim_siglist[0]; if ((sig->sig_flags & DKIM_SIGFLAG_KEYLOADED) == 0) { dkim_error(dkim, "private key load failure"); return DKIM_STAT_INVALID; } tmpbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (tmpbuf == NULL) { dkim_error(dkim, "failed to allocate dynamic string"); return DKIM_STAT_NORESOURCE; } if (dkim->dkim_hdrbuf == NULL) { dkim->dkim_hdrbuf = dkim_dstring_new(dkim, BUFRSZ, MAXBUFRSZ); if (dkim->dkim_hdrbuf == NULL) { dkim_dstring_free(tmpbuf); dkim_error(dkim, "failed to allocate dynamic string"); return DKIM_STAT_NORESOURCE; } } else { dkim_dstring_blank(dkim->dkim_hdrbuf); } /* compute and extract the signature header */ len = dkim_gensighdr(dkim, sig, tmpbuf, DELIMITER); if (len == 0) { dkim_dstring_free(tmpbuf); return DKIM_STAT_INVALID; } if (dkim->dkim_b64sig != NULL) dkim_dstring_cat(tmpbuf, dkim->dkim_b64sig); if (dkim->dkim_margin == 0) { _Bool first = TRUE; for (pv = strtok_r((char *) dkim_dstring_get(tmpbuf), DELIMITER, &ctx); pv != NULL; pv = strtok_r(NULL, DELIMITER, &ctx)) { if (!first) dkim_dstring_cat1(dkim->dkim_hdrbuf, ' '); dkim_dstring_cat(dkim->dkim_hdrbuf, (u_char *) pv); first = FALSE; } } else { _Bool first = TRUE; _Bool forcewrap; int pvlen; int whichlen; char *p; char *q; char *end; char which[MAXTAGNAME + 1]; len = initial; end = which + MAXTAGNAME; for (pv = strtok_r((char *) dkim_dstring_get(tmpbuf), DELIMITER, &ctx); pv != NULL; pv = strtok_r(NULL, DELIMITER, &ctx)) { for (p = pv, q = which; *p != '=' && q <= end; p++, q++) { *q = *p; *(q + 1) = '\0'; } whichlen = strlen(which); /* force wrapping of "b=" ? */ forcewrap = FALSE; if (sig->sig_keytype == DKIM_KEYTYPE_RSA) { u_int siglen; siglen = BASE64SIZE(sig->sig_keybits / 8); if (strcmp(which, "b") == 0 && len + whichlen + siglen + 1 >= dkim->dkim_margin) forcewrap = TRUE; } pvlen = strlen(pv); if (len == 0 || first) { dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) pv, pvlen); len += pvlen; first = FALSE; } else if (forcewrap || len + pvlen > dkim->dkim_margin) { forcewrap = FALSE; dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) "\r\n\t", 3); len = 8; if (strcmp(which, "h") == 0) { /* break at colons */ _Bool ifirst = TRUE; int tmplen; char *tmp; char *ctx2; for (tmp = strtok_r(pv, ":", &ctx2); tmp != NULL; tmp = strtok_r(NULL, ":", &ctx2)) { tmplen = strlen(tmp); if (ifirst) { dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) tmp, tmplen); len += tmplen; ifirst = FALSE; } else if (len + tmplen + 1 > dkim->dkim_margin) { dkim_dstring_cat1(dkim->dkim_hdrbuf, ':'); len += 1; dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) "\r\n\t ", 4); len = 9; dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) tmp, tmplen); len += tmplen; } else { dkim_dstring_cat1(dkim->dkim_hdrbuf, ':'); len += 1; dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) tmp, tmplen); len += tmplen; } } } else if (strcmp(which, "b") == 0 || strcmp(which, "bh") == 0 || strcmp(which, "z") == 0) { /* break at margins */ int offset; int n; char *x; char *y; offset = whichlen + 1; dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) which, whichlen); dkim_dstring_cat1(dkim->dkim_hdrbuf, '='); len += offset; dkim_dstring_cat1(dkim->dkim_hdrbuf, *(pv + offset)); len++; x = pv + offset + 1; y = pv + pvlen; while (x < y) { if (dkim->dkim_margin - len == 0) { dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) "\r\n\t ", 4); len = 9; } n = MIN(dkim->dkim_margin - len, y - x); dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) x, n); x += n; len += n; } } else { /* break at delimiter */ dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) pv, pvlen); len += pvlen; } } else { if (!first) { dkim_dstring_cat1(dkim->dkim_hdrbuf, ' '); len += 1; } first = FALSE; dkim_dstring_catn(dkim->dkim_hdrbuf, (u_char *) pv, pvlen); len += pvlen; } } } *buf = dkim_dstring_get(dkim->dkim_hdrbuf); *buflen = dkim_dstring_len(dkim->dkim_hdrbuf); dkim_dstring_free(tmpbuf); return DKIM_STAT_OK; } /* ** DKIM_GETSIGHDR -- retrieve signature header into a user-provided buffer ** ** Parameters: ** dkim -- libopendkim handle ** buf -- buffer into which to write ** buflen -- bytes available at "buf" ** initial -- width aleady consumed for the first line ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_getsighdr(DKIM *dkim, u_char *buf, size_t buflen, size_t initial) { u_char *p; size_t len; DKIM_STAT status; assert(dkim != NULL); assert(buf != NULL); assert(buflen > 0); status = dkim_getsighdr_d(dkim, initial, &p, &len); if (status != DKIM_STAT_OK) return status; if (len > buflen) { dkim_error(dkim, "generated signature header too large"); return DKIM_STAT_NORESOURCE; } strlcpy((char *) buf, (char *) p, buflen); return DKIM_STAT_OK; } /* ** DKIM_SIG_HDRSIGNED -- retrieve the header list from a signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** hdr -- header name to find ** ** Return value: ** TRUE iff "sig" had a header list in it and the header "hdr" ** appeared in that list. */ _Bool dkim_sig_hdrsigned(DKIM_SIGINFO *sig, u_char *hdr) { size_t len; u_char *c1 = NULL; u_char *c2 = NULL; u_char *start; u_char *p; u_char *hdrlist; assert(sig != NULL); assert(hdr != NULL); hdrlist = dkim_param_get(sig->sig_taglist, (u_char *) "h"); if (hdrlist == NULL) return FALSE; for (p = hdrlist; ; p++) { len = -1; if (*p == ':') { c1 = c2; c2 = p; if (c1 == NULL) { start = hdrlist; len = c2 - start; } else { start = c1 + 1; len = c2 - c1 - 1; } } else if (*p == '\0') { if (c2 != NULL) { start = c2 + 1; len = p - c2 - 1; if (strncasecmp((char *) hdr, (char *) start, len) == 0) return TRUE; } else { if (strcasecmp((char *) hdr, (char *) hdrlist) == 0) return TRUE; } break; } if (len != -1) { if (strncasecmp((char *) hdr, (char *) start, len) == 0) return TRUE; } } return FALSE; } /* ** DKIM_SIG_GETDNSSEC -- retrieve DNSSEC results for a signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** A DKIM_DNSSEC_* constant. */ int dkim_sig_getdnssec(DKIM_SIGINFO *sig) { assert(sig != NULL); return sig->sig_dnssec_key; } /* ** DKIM_SIG_SETDNSSEC -- set DNSSEC results for a signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** dnssec_status -- A DKIM_DNSSEC_* constant ** */ void dkim_sig_setdnssec(DKIM_SIGINFO *sig, int dnssec_status) { assert(sig != NULL); switch (dnssec_status) { case DKIM_DNSSEC_BOGUS: case DKIM_DNSSEC_INSECURE: case DKIM_DNSSEC_SECURE: sig->sig_dnssec_key = dnssec_status; break; default: /* just use the unknown value */ sig->sig_dnssec_key = DKIM_DNSSEC_UNKNOWN; break; } } /* ** DKIM_SIG_GETREPORTINFO -- retrieve reporting information for a signature ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** hfd -- descriptor to canonicalized header (or NULL) (returned) ** bfd -- descriptor to canonicalized body (or NULL) (returned) ** addr -- address buffer (or NULL) ** addrlen -- size of addr ** opts -- options buffer (or NULL) ** optslen -- size of opts ** smtp -- SMTP reply text buffer (or NULL) ** smtplen -- size of smtp ** pct -- requested reporting percentage (or NULL) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getreportinfo(DKIM *dkim, DKIM_SIGINFO *sig, int *hfd, int *bfd, u_char *addr, size_t addrlen, u_char *opts, size_t optslen, u_char *smtp, size_t smtplen, u_int *pct) { DKIM_STAT status; u_char *p; char *sdomain; DKIM_SET *set; struct timeval timeout; unsigned char buf[BUFRSZ]; assert(dkim != NULL); assert(sig != NULL); if (dkim->dkim_state != DKIM_STATE_EOM2 || dkim->dkim_mode != DKIM_MODE_VERIFY) return DKIM_STAT_INVALID; sdomain = dkim_sig_getdomain(sig); /* report descriptors regardless of reporting parameters */ if (sig->sig_hdrcanon != NULL) { switch (sig->sig_hashtype) { #ifdef USE_GNUTLS case DKIM_HASHTYPE_SHA1: case DKIM_HASHTYPE_SHA256: { struct dkim_sha *sha; sha = (struct dkim_sha *) sig->sig_hdrcanon->canon_hash; if (hfd != NULL) *hfd = sha->sha_tmpfd; if (bfd != NULL) { sha = (struct dkim_sha *) sig->sig_bodycanon->canon_hash; *bfd = sha->sha_tmpfd; } break; } #else /* USE_GNUTLS */ case DKIM_HASHTYPE_SHA1: { struct dkim_sha1 *sha1; sha1 = (struct dkim_sha1 *) sig->sig_hdrcanon->canon_hash; if (hfd != NULL) *hfd = sha1->sha1_tmpfd; if (bfd != NULL) { sha1 = (struct dkim_sha1 *) sig->sig_bodycanon->canon_hash; *bfd = sha1->sha1_tmpfd; } break; } # ifdef HAVE_SHA256 case DKIM_HASHTYPE_SHA256: { struct dkim_sha256 *sha256; sha256 = (struct dkim_sha256 *) sig->sig_hdrcanon->canon_hash; if (hfd != NULL) *hfd = sha256->sha256_tmpfd; if (bfd != NULL) { sha256 = (struct dkim_sha256 *) sig->sig_bodycanon->canon_hash; *bfd = sha256->sha256_tmpfd; } break; } # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ default: assert(0); } } /* see if the signature had an "r=y" tag */ set = sig->sig_taglist; if (set == NULL) return DKIM_STAT_INTERNAL; p = dkim_param_get(set, (u_char *) "r"); if (p == NULL || p[0] != 'y' || p[1] != '\0') { if (addr != NULL) addr[0] = '\0'; if (opts != NULL) opts[0] = '\0'; if (smtp != NULL) smtp[0] = '\0'; if (pct != NULL) *pct = (u_int) -1; return DKIM_STAT_OK; } /* see if we've grabbed this set already */ for (set = dkim_set_first(dkim, DKIM_SETTYPE_SIGREPORT); set != NULL; set = dkim_set_next(set, DKIM_SETTYPE_SIGREPORT)) { if (set->set_name != NULL && strcasecmp(set->set_name, sdomain) == 0) break; } /* guess not; go to the DNS to get reporting parameters */ if (set == NULL) { timeout.tv_sec = dkim->dkim_timeout; timeout.tv_usec = 0; memset(buf, '\0', sizeof buf); status = dkim_repinfo(dkim, sig, &timeout, buf, sizeof buf); if (status != DKIM_STAT_OK) return status; if (buf[0] == '\0') return DKIM_STAT_OK; status = dkim_process_set(dkim, DKIM_SETTYPE_SIGREPORT, buf, strlen(buf), NULL, FALSE, sdomain); if (status != DKIM_STAT_OK) return status; for (set = dkim_set_first(dkim, DKIM_SETTYPE_SIGREPORT); set != NULL; set = dkim_set_next(set, DKIM_SETTYPE_SIGREPORT)) { if (set->set_name != NULL && strcasecmp(set->set_name, sdomain) == 0) break; } assert(set != NULL); } if (addr != NULL) { p = dkim_param_get(set, (u_char *) "ra"); if (p != NULL) { memset(addr, '\0', addrlen); (void) dkim_qp_decode(p, addr, addrlen - 1); p = (u_char *) strchr((char *) addr, '@'); if (p != NULL) *p = '\0'; } } if (opts != NULL) { p = dkim_param_get(set, (u_char *) "ro"); if (p != NULL) strlcpy((char *) opts, (char *) p, optslen); } if (smtp != NULL) { p = dkim_param_get(set, (u_char *) "rs"); if (p != NULL) { memset(smtp, '\0', smtplen); (void) dkim_qp_decode(p, smtp, smtplen - 1); } } if (pct != NULL) { p = dkim_param_get(set, (u_char *) "rp"); if (p != NULL) { u_int out; char *q; out = strtoul((char *) p, &q, 10); if (*q == '\0') *pct = out; } } return DKIM_STAT_OK; } /* ** DKIM_SIG_GETIDENTITY -- retrieve identity of the signer ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle (or NULL to choose final one) ** val -- destination buffer ** vallen -- size of destination buffer ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getidentity(DKIM *dkim, DKIM_SIGINFO *sig, u_char *val, size_t vallen) { int len; char *param; struct dkim_set *set; assert(val != NULL); assert(vallen != 0); if (sig == NULL) { if (dkim == NULL) return DKIM_STAT_INVALID; sig = dkim->dkim_signature; if (sig == NULL) return DKIM_STAT_INVALID; } set = sig->sig_taglist; param = (char *) dkim_param_get(set, (u_char *) "i"); if (param == NULL) { param = (char *) dkim_param_get(set, (u_char *) "d"); if (param == NULL) return DKIM_STAT_INTERNAL; len = snprintf((char *) val, vallen, "@%s", param); return (len < vallen ? DKIM_STAT_OK : DKIM_STAT_NORESOURCE); } else { len = dkim_qp_decode((u_char *) param, (u_char *) val, vallen - 1); if (len == -1) { return DKIM_STAT_SYNTAX; } else if (len >= vallen) { return DKIM_STAT_NORESOURCE; } else { val[len] = '\0'; return DKIM_STAT_OK; } } } /* ** DKIM_SIG_GETCANONLEN -- return canonicalized and total body lengths ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** msglen -- total body length (returned) ** canonlen -- total canonicalized length (returned) ** signlen -- maximum signed length (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getcanonlen(DKIM *dkim, DKIM_SIGINFO *sig, ssize_t *msglen, ssize_t *canonlen, ssize_t *signlen) { assert(dkim != NULL); assert(sig != NULL); if (msglen != NULL) *msglen = dkim->dkim_bodylen; if (canonlen != NULL) { if (sig->sig_bodycanon == NULL) return DKIM_STAT_INTERNAL; *canonlen = sig->sig_bodycanon->canon_wrote; } if (signlen != NULL) { if (sig->sig_bodycanon == NULL) return DKIM_STAT_INTERNAL; *signlen = sig->sig_bodycanon->canon_length; } return DKIM_STAT_OK; } /* ** DKIM_SIG_GETFLAGS -- retreive signature handle flags ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** An unsigned integer which is a bitwise-OR of the DKIM_SIGFLAG_* ** constants currently set in the provided handle. */ unsigned int dkim_sig_getflags(DKIM_SIGINFO *sig) { assert(sig != NULL); return sig->sig_flags; } /* ** DKIM_SIG_GETBH -- retreive signature handle "bh" test state ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** An integer that is one of the DKIM_SIGBH_* constants ** indicating the current state of "bh" evaluation of the signature. */ int dkim_sig_getbh(DKIM_SIGINFO *sig) { assert(sig != NULL); return sig->sig_bh; } /* ** DKIM_SIG_GETKEYSIZE -- retrieve key size (in bits) when verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** bits -- number of bits in the key (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getkeysize(DKIM_SIGINFO *sig, unsigned int *bits) { assert(sig != NULL); assert(bits != NULL); if (sig->sig_keybits == 0 && sig->sig_signalg != DKIM_SIGN_ED25519SHA256) return DKIM_STAT_INVALID; *bits = sig->sig_keybits; return DKIM_STAT_OK; } /* ** DKIM_SIG_GETSIGNALG -- retrieve signature algorithm when verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** alg -- signature algorithm used (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getsignalg(DKIM_SIGINFO *sig, dkim_alg_t *alg) { assert(sig != NULL); assert(alg != NULL); *alg = sig->sig_signalg; return DKIM_STAT_OK; } /* ** DKIM_SIG_GETSIGNTIME -- retrieve signature timestamp ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** when -- signature timestamp (returned) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getsigntime(DKIM_SIGINFO *sig, uint64_t *when) { assert(sig != NULL); assert(when != NULL); if (sig->sig_timestamp == 0) return DKIM_STAT_INVALID; *when = sig->sig_timestamp; return DKIM_STAT_OK; } /* ** DKIM_SIG_GETCANONS -- retrieve canonicalizations used when signing ** ** Parameters: ** sig -- DKIM_SIGINFO handle from which to retrieve canonicalizations ** hdr -- Pointer to a dkim_canon_t where the header canonicalization ** should be stored ** body -- Pointer to a dkim_canon_t where the body canonicalization ** should be stored ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getcanons(DKIM_SIGINFO *sig, dkim_canon_t *hdr, dkim_canon_t *body) { assert(sig != NULL); if (hdr != NULL) *hdr = sig->sig_hdrcanonalg; if (body != NULL) *body = sig->sig_bodycanonalg; return DKIM_STAT_OK; } /* ** DKIM_GET_SIGNER -- get DKIM signature's signer ** ** Parameters: ** dkim -- DKIM signing handle ** ** Parameters: ** Pointer to a buffer containing the signer previously requested, ** or NULL if none. */ const unsigned char * dkim_get_signer(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_signer; } /* ** DKIM_SET_SIGNER -- set DKIM signature's signer ** ** Parameters: ** dkim -- DKIM signing handle ** signer -- signer to store ** ** Parameters: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_set_signer(DKIM *dkim, const unsigned char *signer) { assert(dkim != NULL); assert(signer != NULL); if (dkim->dkim_mode != DKIM_MODE_SIGN) return DKIM_STAT_INVALID; if (dkim->dkim_signer == NULL) { dkim->dkim_signer = DKIM_MALLOC(dkim, MAXADDRESS + 1); if (dkim->dkim_signer == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", MAXADDRESS + 1); return DKIM_STAT_NORESOURCE; } } strlcpy((char *) dkim->dkim_signer, (char *) signer, MAXADDRESS + 1); return DKIM_STAT_OK; } /* ** DKIM_GETERROR -- return any stored error string from within the DKIM ** context handle ** ** Parameters: ** dkim -- DKIM handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ const char * dkim_geterror(DKIM *dkim) { assert(dkim != NULL); return (const char *) dkim->dkim_error; } /* ** DKIM_GETPARTIAL -- return if the DKIM handle is to be signed using ** the bodylength tag (l=) ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** True iff the signature is to include a body length tag */ _Bool dkim_getpartial(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_partial; } /* ** DKIM_SETPARTIAL -- set the DKIM handle to sign using the DKIM body length ** tag (l=) ** ** Parameters: ** dkim -- DKIM handle ** value -- new Boolean value ** ** Return value: ** DKIM_STAT_INVALID -- "dkim" referenced a verification handle ** DKIM_STAT_OK -- otherwise */ DKIM_STAT dkim_setpartial(DKIM *dkim, _Bool value) { assert(dkim != NULL); if (dkim->dkim_mode != DKIM_MODE_SIGN) return DKIM_STAT_INVALID; dkim->dkim_partial = value; return DKIM_STAT_OK; } /* ** DKIM_SET_MARGIN -- set the margin to use when generating signatures ** ** Parameters: ** dkim -- DKIM handle ** value -- new margin value ** ** Return value: ** DKIM_STAT_INVALID -- "dkim" referenced a verification handle, ** "value" was negative, or this is being called ** after dkim_eom() completed ** DKIM_STAT_OK -- otherwise */ DKIM_STAT dkim_set_margin(DKIM *dkim, int value) { assert(dkim != NULL); if (dkim->dkim_mode != DKIM_MODE_SIGN || value < 0 || dkim->dkim_state >= DKIM_STATE_EOM2) return DKIM_STAT_INVALID; dkim->dkim_margin = (size_t) value; return DKIM_STAT_OK; } /* ** DKIM_GETRESULTSTR -- translate a DKIM_STAT_* constant to a string ** ** Parameters: ** result -- DKIM_STAT_* constant to translate ** ** Return value: ** Pointer to a text describing "result", or NULL if none exists */ const char * dkim_getresultstr(DKIM_STAT result) { return dkim_code_to_name(results, result); } /* ** DKIM_SET_DNS_CALLBACK -- set the DNS wait callback ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call; should take an opaque context pointer ** interval -- how often to call back ** ** Return value: ** DKIM_STAT_OK -- success ** DKIM_STAT_INVALID -- invalid use ** DKIM_STAT_NOTIMPLEMENT -- underlying resolver doesn't support callbacks */ DKIM_STAT dkim_set_dns_callback(DKIM_LIB *libopendkim, void (*func)(const void *context), unsigned int interval) { assert(libopendkim != NULL); if (func != NULL && interval == 0) return DKIM_STAT_INVALID; libopendkim->dkiml_dns_callback = func; libopendkim->dkiml_callback_int = interval; return DKIM_STAT_OK; } /* ** DKIM_SET_USER_CONTEXT -- set user context pointer ** ** Parameters: ** dkim -- DKIM handle ** ctx -- opaque context pointer ** ** Return value: ** DKIM_STAT_OK */ DKIM_STAT dkim_set_user_context(DKIM *dkim, void *ctx) { assert(dkim != NULL); dkim->dkim_user_context = (const void *) ctx; return DKIM_STAT_OK; } /* ** DKIM_GET_USER_CONTEXT -- get user context pointer ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** User context associated with a DKIM handle */ void * dkim_get_user_context(DKIM *dkim) { assert(dkim != NULL); return (void *) dkim->dkim_user_context; } /* ** DKIM_GETMODE -- return the mode (signing, verifying, etc.) of a handle ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_MODE_* constant. */ int dkim_getmode(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_mode; } /* ** DKIM_GETDOMAIN -- retrieve policy domain from a DKIM context ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to the domain used for policy checking or NULL if no domain ** could be determined. */ u_char * dkim_getdomain(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_domain; } /* ** DKIM_GETUSER -- retrieve sending user (local-part) from a DKIM context ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to the apparent sending user (local-part) or NULL if not known. */ u_char * dkim_getuser(DKIM *dkim) { assert(dkim != NULL); return dkim->dkim_user; } /* ** DKIM_SET_KEY_LOOKUP -- set the key lookup function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ DKIM_STAT dkim_set_key_lookup(DKIM_LIB *libopendkim, DKIM_STAT (*func)(DKIM *dkim, DKIM_SIGINFO *sig, u_char *buf, size_t buflen)) { assert(libopendkim != NULL); libopendkim->dkiml_key_lookup = func; return DKIM_STAT_OK; } /* ** DKIM_SET_SIGNATURE_HANDLE -- set the user handle allocation function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK -- success */ DKIM_STAT dkim_set_signature_handle(DKIM_LIB *libopendkim, void * (*func)(void *closure)) { assert(libopendkim != NULL); libopendkim->dkiml_sig_handle = func; return DKIM_STAT_OK; } /* ** DKIM_SET_SIGNATURE_HANDLE_FREE -- set the user handle deallocation function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ DKIM_STAT dkim_set_signature_handle_free(DKIM_LIB *libopendkim, void (*func)(void *closure, void *user)) { assert(libopendkim != NULL); libopendkim->dkiml_sig_handle_free = func; return DKIM_STAT_OK; } /* ** DKIM_SET_SIGNATURE_TAGVALUES -- set the user handle population function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ DKIM_STAT dkim_set_signature_tagvalues(DKIM_LIB *libopendkim, void (*func)(void *user, dkim_param_t pcode, const u_char *param, const u_char *value)) { assert(libopendkim != NULL); libopendkim->dkiml_sig_tagvalues = func; return DKIM_STAT_OK; } /* ** DKIM_SET_PRESCREEN -- set the user prescreen function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ DKIM_STAT dkim_set_prescreen(DKIM_LIB *libopendkim, DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs)) { assert(libopendkim != NULL); libopendkim->dkiml_prescreen = func; return DKIM_STAT_OK; } /* ** DKIM_SET_FINAL -- set the user final scan function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ DKIM_STAT dkim_set_final(DKIM_LIB *libopendkim, DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs)) { assert(libopendkim != NULL); libopendkim->dkiml_final = func; return DKIM_STAT_OK; } /* ** DKIM_SIG_GETCONTEXT -- retrieve user-provided context from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract context ** ** Return value: ** Pointer to the user context provided by an earlier call to the ** handle allocator (see above), or NULL if none was ever set. */ void * dkim_sig_getcontext(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); return siginfo->sig_context; } /* ** DKIM_SIG_GETSELECTOR -- retrieve selector from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract the selector ** ** Return value: ** Pointer to the selector associated with the DKIM_SIGINFO. */ unsigned char * dkim_sig_getselector(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); return siginfo->sig_selector; } /* ** DKIM_SIG_GETDOMAIN -- retrieve domain from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract the domain ** ** Return value: ** Pointer to the domain associated with the DKIM_SIGINFO. */ unsigned char * dkim_sig_getdomain(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); return siginfo->sig_domain; } /* ** DKIM_SIG_GETALGORITHM -- retrieve algorithm from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract the ** algorithm ** ** Return value: ** Pointer to the algorithm associated with the DKIM_SIGINFO. */ unsigned char * dkim_sig_getalgorithm(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); return (unsigned char *) dkim_code_to_name(algorithms, siginfo->sig_signalg); } /* ** DKIM_SIG_SETERROR -- set an error code in a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract context ** err -- error code to store ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_seterror(DKIM_SIGINFO *siginfo, int err) { assert(siginfo != NULL); if (siginfo->sig_error != DKIM_SIGERROR_UNKNOWN) return DKIM_STAT_INVALID; siginfo->sig_error = err; return DKIM_STAT_OK; } /* ** DKIM_SIG_GETERROR -- retrieve an error code from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract context ** ** Return value: ** A DKIM_SIGERROR_* constant. */ int dkim_sig_geterror(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); return siginfo->sig_error; } /* ** DKIM_SIG_GETERRORSTR -- translate a DKIM_SIGERROR_* constant to a string ** ** Parameters: ** sigerr -- DKIM_SIGERROR_* constant to translate ** ** Return value: ** A pointer to a human-readable expression of "sigerr", or NULL if none ** exists. */ const char * dkim_sig_geterrorstr(DKIM_SIGERROR sigerr) { return dkim_code_to_name(sigerrors, sigerr); } /* ** DKIM_SIG_IGNORE -- mark a signature referenced by a DKIM_SIGINFO with ** an "ignore" flag ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO to update ** ** Return value: ** None. */ void dkim_sig_ignore(DKIM_SIGINFO *siginfo) { assert(siginfo != NULL); siginfo->sig_flags |= DKIM_SIGFLAG_IGNORE; } /* ** DKIM_SSL_VERSION -- return version of OpenSSL that was used to build ** the library ** ** Parameters: ** None. ** ** Return value: ** The constant OPENSSL_VERSION_NUMBER as defined by OpenSSL. */ unsigned long dkim_ssl_version(void) { #ifdef USE_GNUTLS return (GNUTLS_VERSION_NUMBER << 8); #else /* USE_GNUTLS */ return OPENSSL_VERSION_NUMBER; #endif /* USE_GNUTLS */ } /* ** DKIM_FLUSH_CACHE -- purge expired records from the cache ** ** Parameters: ** lib -- DKIM library handle, returned by dkim_init() ** ** Return value: ** -1 -- caching is not in effect ** >= 0 -- number of purged records */ int dkim_flush_cache(DKIM_LIB *lib) { #ifdef QUERY_CACHE int err; #endif /* QUERY_CACHE */ assert(lib != NULL); #ifdef QUERY_CACHE if (lib->dkiml_cache == NULL) return -1; return dkim_cache_expire(lib->dkiml_cache, 0, &err); #else /* QUERY_CACHE */ return -1; #endif /* QUERY_CACHE */ } /* ** DKIM_GETCACHESTATS -- retrieve cache statistics ** ** Parameters: ** lib -- DKIM library handle, returned by dkim_init() ** queries -- number of queries handled (returned) ** hits -- number of cache hits (returned) ** expired -- number of expired hits (returned) ** keys -- number of keys in the cache (returned) ** reset -- if TRUE, resets the queries, hits, and expired counters ** ** Return value: ** DKIM_STAT_OK -- request completed ** DKIM_STAT_INVALID -- cache not initialized ** DKIM_STAT_NOTIMPLEMENT -- function not implemented ** ** Notes: ** Any of the parameters may be NULL if the corresponding datum ** is not of interest. */ DKIM_STAT dkim_getcachestats(DKIM_LIB *lib, u_int *queries, u_int *hits, u_int *expired, u_int *keys, _Bool reset) { #ifdef QUERY_CACHE assert(lib != NULL); if (lib->dkiml_cache == NULL) return DKIM_STAT_INVALID; dkim_cache_stats(lib->dkiml_cache, queries, hits, expired, keys, reset); return DKIM_STAT_OK; #else /* QUERY_CACHE */ return DKIM_STAT_NOTIMPLEMENT; #endif /* QUERY_CACHE */ } /* ** DKIM_CONDITIONAL -- set conditional domain on a signature ** ** Parameters: ** dkim -- signing handle ** domain -- domain name upon which this signature shall depend ** ** Return value: ** DKIM_STAT_OK -- request completed ** DKIM_STAT_NOTIMPLEMENT -- function not implemented */ DKIM_STAT dkim_conditional(DKIM *dkim, u_char *domain) { #ifdef _FFR_CONDITIONAL dkim->dkim_conditional = domain; return DKIM_STAT_OK; #else /* _FFR_CONDITIONAL */ return DKIM_STAT_NOTIMPLEMENT; #endif /* _FFR_CONDITIONAL */ } /* /* ** DKIM_GET_SIGSUBSTRING -- retrieve a minimal signature substring for ** disambiguation ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** buf -- buffer into which to put the substring ** buflen -- bytes available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_get_sigsubstring(DKIM *dkim, DKIM_SIGINFO *sig, char *buf, size_t *buflen) { int c; int d; int x; int b1len; int b2len; int minlen; char *b1; char *b2; assert(dkim != NULL); assert(sig != NULL); assert(buf != NULL); assert(buflen != NULL); if (dkim->dkim_minsiglen == 0) { dkim->dkim_minsiglen = MINSIGLEN; for (c = 0; c < dkim->dkim_sigcount - 1; c++) { b1 = (char *) dkim_param_get(dkim->dkim_siglist[c]->sig_taglist, (u_char *) "b"); if (b1 == NULL) continue; b1len = strlen(b1); for (d = c + 1; d < dkim->dkim_sigcount; d++) { b2 = (char *) dkim_param_get(dkim->dkim_siglist[d]->sig_taglist, (u_char *) "b"); if (b2 == NULL) continue; if (strcmp(b1, b2) == 0) break; if (strncmp(b1, b2, dkim->dkim_minsiglen) != 0) continue; b2len = strlen(b2); minlen = MIN(b1len, b2len); for (x = dkim->dkim_minsiglen; x < minlen; x++) { if (b1[x] != b2[x]) break; } dkim->dkim_minsiglen = x + 1; } } } b1 = (char *) dkim_param_get(sig->sig_taglist, (u_char *) "b"); if (b1 == NULL) return DKIM_STAT_SYNTAX; minlen = MIN(*buflen, dkim->dkim_minsiglen); strncpy(buf, b1, minlen); if (minlen < *buflen) buf[minlen] = '\0'; *buflen = minlen; return DKIM_STAT_OK; } /* ** DKIM_LIBFEATURE -- determine whether or not a particular library feature ** is actually available ** ** Parameters: ** lib -- library handle ** fc -- feature code to check ** ** Return value: ** TRUE iff the specified feature was compiled in */ _Bool dkim_libfeature(DKIM_LIB *lib, u_int fc) { u_int idx; u_int offset; idx = fc / (8 * sizeof(int)); offset = fc % (8 * sizeof(int)); if (idx > lib->dkiml_flsize) return FALSE; return ((lib->dkiml_flist[idx] & (1 << offset)) != 0); } /* ** DKIM_LIBVERSION -- return version of libopendkim at runtime ** ** Parameters: ** None. ** ** Return value: ** Library version, i.e. value of the OPENDKIM_LIB_VERSION macro. */ uint32_t dkim_libversion(void) { return OPENDKIM_LIB_VERSION; } /* ** DKIM_SIG_GETTAGVALUE -- retrieve a tag's value from a signature or its key ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** keytag -- TRUE iff we want a key's tag ** tag -- name of the tag of interest ** ** Return value: ** Pointer to the string containing the value of the requested key, ** or NULL if not present. ** ** Notes: ** This was added for use in determining whether or not a key or ** signature contained particular data, for gathering general statistics ** about DKIM use. It is not intended to give applications direct access ** to unprocessed signature or key data. The data returned has not ** necessarily been vetted in any way. Caveat emptor. */ u_char * dkim_sig_gettagvalue(DKIM_SIGINFO *sig, _Bool keytag, u_char *tag) { DKIM_SET *set; assert(sig != NULL); assert(tag != NULL); if (keytag) set = sig->sig_keytaglist; else set = sig->sig_taglist; if (set == NULL) return NULL; else return dkim_param_get(set, tag); } /* ** DKIM_SIG_GETSIGNEDHDRS -- retrieve the signed header fields covered by ** a signature that passed ** ** Parameters: ** dkim -- DKIM instance ** sig -- signature ** hdrs -- rectangular array of header field strings ** hdrlen -- length of each element of "hdrs" ** nhdrs -- size of "hdrs" array (updated) ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getsignedhdrs(DKIM *dkim, DKIM_SIGINFO *sig, u_char *hdrs, size_t hdrlen, u_int *nhdrs) { int status; u_int n; u_char *h; u_char *p; struct dkim_header **sighdrs; assert(dkim != NULL); assert(sig != NULL); assert(nhdrs != NULL); if ((sig->sig_flags & DKIM_SIGFLAG_PASSED) == 0 || sig->sig_bh != DKIM_SIGBH_MATCH) return DKIM_STAT_INVALID; h = dkim_param_get(sig->sig_taglist, "h"); assert(h != NULL); n = 1; for (p = h; *p != '\0'; p++) { if (*p == ':') n++; } if (*nhdrs < n) { *nhdrs = n; return DKIM_STAT_NORESOURCE; } assert(hdrs != NULL); sighdrs = (struct dkim_header **) DKIM_MALLOC(dkim, sizeof(struct dkim_header *) * n); if (sighdrs == NULL) { *nhdrs = 0; return DKIM_STAT_NORESOURCE; } status = dkim_canon_selecthdrs(dkim, h, sighdrs, n); if (status == -1) { DKIM_FREE(dkim, sighdrs); return DKIM_STAT_INTERNAL; } *nhdrs = status; for (n = 0; n < status; n++) strlcpy(&hdrs[n * hdrlen], sighdrs[n]->hdr_text, hdrlen); DKIM_FREE(dkim, sighdrs); return DKIM_STAT_OK; } /* ** DKIM_DNS_SET_QUERY_SERVICE -- stores a handle representing the DNS ** query service to be used, returning any ** previous handle ** ** Parameters: ** lib -- DKIM library handle ** h -- handle to be used ** ** Return value: ** Previously stored handle, or NULL if none. */ void * dkim_dns_set_query_service(DKIM_LIB *lib, void *h) { void *old; old = lib->dkiml_dns_service; lib->dkiml_dns_service = h; return old; } /* ** DKIM_DNS_SET_QUERY_START -- stores a pointer to a query start function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to start queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- receives handle stored by ** dkim_dns_set_query_service() ** int type -- DNS RR query type (C_IN assumed) ** char *query -- question to ask ** char *buf -- buffer into which to write reply ** size_t buflen -- size of buf ** void **qh -- returned query handle */ void dkim_dns_set_query_start(DKIM_LIB *lib, int (*func)(void *, int, unsigned char *, unsigned char *, size_t, void **)) { assert(lib != NULL); lib->dkiml_dns_start = func; } /* ** DKIM_DNS_SET_QUERY_CANCEL -- stores a pointer to a query cancel function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to cancel running queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- query handle to be canceled */ void dkim_dns_set_query_cancel(DKIM_LIB *lib, int (*func)(void *, void *)) { assert(lib != NULL); lib->dkiml_dns_cancel = func; } /* ** DKIM_DNS_SET_INIT -- stores a pointer to a resolver init function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void **srv -- DNS service handle (updated) */ void dkim_dns_set_init(DKIM_LIB *lib, int (*func)(void **)) { assert(lib != NULL); lib->dkiml_dns_init = func; } /* ** DKIM_DNS_SET_CLOSE -- stores a pointer to a resolver shutdown function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns void ** void *srv -- DNS service handle */ void dkim_dns_set_close(DKIM_LIB *lib, void (*func)(void *)) { assert(lib != NULL); lib->dkiml_dns_close = func; } /* ** DKIM_DNS_SET_NSLIST -- stores a pointer to a NS list update function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to update NS list ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *dns -- DNS service handle ** const char *nslist -- comma-separated list of nameservers */ void dkim_dns_set_nslist(DKIM_LIB *lib, int (*func)(void *, const char *)) { assert(lib != NULL); lib->dkiml_dns_setns = func; } /* ** DKIM_DNS_SET_CONFIG -- stores a pointer to a resolver configuration ** function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to update resolver configuration ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *dns -- DNS service handle ** const char *config -- opaque configuration string */ void dkim_dns_set_config(DKIM_LIB *lib, int (*func)(void *, const char *)) { assert(lib != NULL); lib->dkiml_dns_config = func; } /* ** DKIM_DNS_SET_TRUSTANCHOR -- stores a pointer to a trust anchor ** configuration function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to update trust anchor configuration ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *dns -- DNS service handle ** const char *trustanchor -- opaque trust anchor string */ void dkim_dns_set_trustanchor(DKIM_LIB *lib, int (*func)(void *, const char *)) { assert(lib != NULL); lib->dkiml_dns_trustanchor = func; } /* ** DKIM_DNS_SET_QUERY_WAITREPLY -- stores a pointer to wait for a DNS reply ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to wait for a reply ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- handle of query that has completed ** struct timeval *timeout -- how long to wait ** size_t *bytes -- bytes returned ** int *error -- error code returned ** int *dnssec -- DNSSEC status returned */ void dkim_dns_set_query_waitreply(DKIM_LIB *lib, int (*func)(void *, void *, struct timeval *, size_t *, int *, int *)) { assert(lib != NULL); lib->dkiml_dns_waitreply = func; } /* ** DKIM_DNS_NSLIST -- requests update to a nameserver list ** ** Parameters: ** lib -- DKIM library handle ** nslist -- comma-separated list of nameservers to use ** ** Return value: ** A DKIM_DNS_* constant. */ int dkim_dns_nslist(DKIM_LIB *lib, const char *nslist) { int status; assert(lib != NULL); assert(nslist != NULL); if (lib->dkiml_dns_setns != NULL) { status = lib->dkiml_dns_setns(lib->dkiml_dns_service, nslist); if (status != 0) return DKIM_DNS_ERROR; } return DKIM_DNS_SUCCESS; } /* ** DKIM_DNS_INIT -- force nameserver (re)initialization ** ** Parameters: ** lib -- DKIM library handle ** ** Return value: ** A DKIM_DNS_* constant. */ int dkim_dns_init(DKIM_LIB *lib) { int status; assert(lib != NULL); if (lib->dkiml_dnsinit_done) return DKIM_DNS_INVALID; if (lib->dkiml_dns_close != NULL && lib->dkiml_dns_service != NULL) { lib->dkiml_dns_close(lib->dkiml_dns_service); lib->dkiml_dns_service = NULL; } if (lib->dkiml_dns_init != NULL) status = lib->dkiml_dns_init(&lib->dkiml_dns_service); else status = DKIM_DNS_SUCCESS; if (status == DKIM_DNS_SUCCESS) lib->dkiml_dnsinit_done = TRUE; return status; } /* ** DKIM_DNS_CLOSE -- force nameserver shutdown ** ** Parameters: ** lib -- DKIM library handle ** ** Return value: ** A DKIM_DNS_* constant. */ int dkim_dns_close(DKIM_LIB *lib) { assert(lib != NULL); if (lib->dkiml_dnsinit_done && lib->dkiml_dns_close != NULL && lib->dkiml_dns_service != NULL) { lib->dkiml_dns_close(lib->dkiml_dns_service); lib->dkiml_dns_service = NULL; } lib->dkiml_dnsinit_done = FALSE; return DKIM_DNS_SUCCESS; } /* ** DKIM_DNS_CONFIG -- requests a change to resolver configuration ** ** Parameters: ** lib -- DKIM library handle ** config -- opaque configuration string ** ** Return value: ** A DKIM_DNS_* constant. */ int dkim_dns_config(DKIM_LIB *lib, const char *config) { int status; assert(lib != NULL); assert(config != NULL); if (lib->dkiml_dns_config != NULL) { status = lib->dkiml_dns_config(lib->dkiml_dns_service, config); if (status != 0) return DKIM_DNS_ERROR; } return DKIM_DNS_SUCCESS; } /* ** DKIM_DNS_TRUSTANCHOR -- requests a change to resolver trust anchor data ** ** Parameters: ** lib -- DKIM library handle ** trust -- opaque trust anchor string ** ** Return value: ** A DKIM_DNS_* constant. */ int dkim_dns_trustanchor(DKIM_LIB *lib, const char *trust) { int status; assert(lib != NULL); assert(trust != NULL); if (lib->dkiml_dns_trustanchor != NULL) { status = lib->dkiml_dns_trustanchor(lib->dkiml_dns_service, trust); if (status != 0) return DKIM_DNS_ERROR; } return DKIM_DNS_SUCCESS; } /* ** DKIM_ADD_QUERYMETHOD -- add a query method ** ** Parameters: ** dkim -- DKIM signing handle to extend ** type -- type of query to add ** options -- options to include ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_add_querymethod(DKIM *dkim, const char *type, const char *options) { u_char *p; struct dkim_qmethod *q; struct dkim_qmethod *lastq; char tmp[BUFRSZ + 1]; assert(dkim != NULL); assert(type != NULL); if (dkim->dkim_mode != DKIM_MODE_SIGN) return DKIM_STAT_INVALID; /* confirm valid syntax, per RFC6376 */ for (p = (u_char *) type; *p != '\0'; p++) { if (!(isascii(*p) && (isalpha(*p) || (p != (u_char *) type && (isalnum(*p) || (*(p+1) != '\0' && *p == '-')))))) return DKIM_STAT_INVALID; } /* do dkim-qp-encode step */ if (options != NULL) { int len; memset(tmp, '\0', sizeof tmp); len = dkim_qp_encode((u_char *) options, tmp, sizeof tmp); if (len == -1) { dkim_error(dkim, "can't encode query options", sizeof(struct dkim_qmethod)); return DKIM_STAT_NORESOURCE; } } /* check for duplicates */ lastq = NULL; for (q = dkim->dkim_querymethods; q != NULL; q = q->qm_next) { lastq = q; if (strcasecmp(q->qm_type, type) == 0 && ((q->qm_options == NULL && options == NULL) || (q->qm_options != NULL && options != NULL && strcasecmp(q->qm_options, tmp) == 0))) return DKIM_STAT_INVALID; } q = (struct dkim_qmethod *) DKIM_MALLOC(dkim, sizeof(struct dkim_qmethod)); if (q == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_qmethod)); return DKIM_STAT_NORESOURCE; } q->qm_type = dkim_strdup(dkim, type, 0); if (q->qm_type == NULL) { DKIM_FREE(dkim, q); dkim_error(dkim, "unable to allocate %d byte(s)", strlen(type) + 1); return DKIM_STAT_NORESOURCE; } if (options != NULL) { q->qm_options = dkim_strdup(dkim, tmp, 0); if (q->qm_options == NULL) { DKIM_FREE(dkim, q->qm_type); DKIM_FREE(dkim, q); dkim_error(dkim, "unable to allocate %d byte(s)", strlen(options) + 1); return DKIM_STAT_NORESOURCE; } } else { q->qm_options = NULL; } q->qm_next = NULL; if (lastq == NULL) dkim->dkim_querymethods = q; else lastq->qm_next = q; return DKIM_STAT_OK; } /* ** DKIM_ADD_XTAG -- add an extension tag/value ** ** Parameters: ** dkim -- DKIM signing handle to extend ** tag -- name of tag to add ** value -- value to include ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** A value that contains spaces won't be wrapped nicely by the signature ** generation code. Support for this should be added later. */ DKIM_STAT dkim_add_xtag(DKIM *dkim, const char *tag, const char *value) { u_char last = '\0'; dkim_param_t pcode; u_char *p; struct dkim_xtag *x; assert(dkim != NULL); assert(tag != NULL); assert(value != NULL); if (dkim->dkim_mode != DKIM_MODE_SIGN) return DKIM_STAT_INVALID; /* check that it's not in sigparams */ if (tag[0] == '\0' || value[0] == '\0') return DKIM_STAT_INVALID; pcode = dkim_name_to_code(sigparams, tag); if (pcode != (dkim_param_t) -1) return DKIM_STAT_INVALID; /* confirm valid syntax, per RFC6376 */ for (p = (u_char *) tag; *p != '\0'; p++) { if (!(isascii(*p) && (isalnum(*p) || *p == '_'))) return DKIM_STAT_INVALID; } if (value[0] == '\n' || value[0] == '\r' || value[0] == '\t' || value[0] == ' ') return DKIM_STAT_INVALID; for (p = (u_char *) value; *p != '\0'; p++) { /* valid characters in general */ if (!(*p == '\n' || *p == '\r' || *p == '\t' || *p == ' ' || (*p >= 0x21 && *p <= 0x7e && *p != 0x3b))) return DKIM_STAT_INVALID; /* CR has to be followed by LF */ if (last == '\r' && *p != '\n') return DKIM_STAT_INVALID; /* LF has to be followed by space or tab */ if (last == '\n' && *p != ' ' && *p != '\t') return DKIM_STAT_INVALID; last = *p; } /* can't end with space */ if (last == '\n' || last == '\r' || last == '\t' || last == ' ') return DKIM_STAT_INVALID; /* check for dupicates */ for (x = dkim->dkim_xtags; x != NULL; x = x->xt_next) { if (strcmp(x->xt_tag, tag) == 0) return DKIM_STAT_INVALID; } x = (struct dkim_xtag *) DKIM_MALLOC(dkim, sizeof(struct dkim_xtag)); if (x == NULL) { dkim_error(dkim, "unable to allocate %d byte(s)", sizeof(struct dkim_xtag)); return DKIM_STAT_NORESOURCE; } x->xt_tag = dkim_strdup(dkim, tag, 0); x->xt_value = dkim_strdup(dkim, value, 0); x->xt_next = dkim->dkim_xtags; dkim->dkim_xtags = x; return DKIM_STAT_OK; } /* ** DKIM_QI_GETNAME -- retrieve the DNS name from a DKIM_QUERYINFO object ** ** Parameters: ** query -- DKIM_QUERYINFO handle ** ** Return value: ** A pointer to a NULL-terminated string indicating the name to be ** queried, or NULL on error. */ const char * dkim_qi_getname(DKIM_QUERYINFO *query) { assert(query != NULL); return query->dq_name; } /* ** DKIM_QI_GETTYPE -- retrieve the DNS RR type from a DKIM_QUERYINFO object ** ** Parameters: ** query -- DKIM_QUERYINFO handle ** ** Return value: ** The DNS RR type to be queried, or -1 on error. */ int dkim_qi_gettype(DKIM_QUERYINFO *query) { assert(query != NULL); return query->dq_type; } /* ** DKIM_SIG_GETQUERIES -- retrieve the queries needed to validate a signature ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** qi -- DKIM_QUERYINFO handle array (returned) ** nqi -- number of entries in the "qi" array ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT dkim_sig_getqueries(DKIM *dkim, DKIM_SIGINFO *sig, DKIM_QUERYINFO ***qi, unsigned int *nqi) { DKIM_QUERYINFO **new; DKIM_QUERYINFO *newp; assert(dkim != NULL); assert(sig != NULL); assert(qi != NULL); assert(nqi != NULL); new = DKIM_MALLOC(dkim, sizeof(struct dkim_queryinfo *)); if (new == NULL) return DKIM_STAT_NORESOURCE; newp = DKIM_MALLOC(dkim, sizeof(struct dkim_queryinfo)); if (newp == NULL) { DKIM_FREE(dkim, new); return DKIM_STAT_NORESOURCE; } memset(newp, '\0', sizeof(struct dkim_queryinfo)); if (sig->sig_selector != NULL && sig->sig_domain != NULL) { newp->dq_type = T_TXT; snprintf((char *) newp->dq_name, sizeof newp->dq_name, "%s.%s.%s", sig->sig_selector, DKIM_DNSKEYNAME, sig->sig_domain); } new[0] = newp; *qi = new; *nqi = 1; return DKIM_STAT_OK; } /* ** DKIM_SIG_GETHASHES -- retrieve hashes ** ** Parameters: ** sig -- signature from which to get completed hashes ** hh -- pointer to header hash buffer (returned) ** hhlen -- bytes used at hh (returned) ** bh -- pointer to body hash buffer (returned) ** bhlen -- bytes used at bh (returned) ** ** Return value: ** DKIM_STAT_OK -- successful completion ** DKIM_STAT_INVALID -- hashing hasn't been completed */ DKIM_STAT dkim_sig_gethashes(DKIM_SIGINFO *sig, void **hh, size_t *hhlen, void **bh, size_t *bhlen) { return dkim_canon_gethashes(sig, hh, hhlen, bh, bhlen); } /* ** DKIM_SIGNHDRS -- set the list of header fields to sign for a signature, ** overriding the library default ** ** Parameters: ** dkim -- DKIM signing handle to be affected ** hdrlist -- array of names of header fields that should be signed ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** "hdrlist" can be NULL if the library's default is to be used. */ DKIM_STAT dkim_signhdrs(DKIM *dkim, const char **hdrlist) { assert(dkim != NULL); if (dkim->dkim_hdrre != NULL) regfree(dkim->dkim_hdrre); if (hdrlist != NULL) { int status; char buf[BUFRSZ + 1]; if (dkim->dkim_hdrre == NULL) { dkim->dkim_hdrre = malloc(sizeof(regex_t)); if (dkim->dkim_hdrre == NULL) { dkim_error(dkim, "could not allocate %d bytes", sizeof(regex_t)); return DKIM_STAT_INTERNAL; } } memset(buf, '\0', sizeof buf); (void) strlcpy(buf, "^(", sizeof buf); if (!dkim_hdrlist((u_char *) buf, sizeof buf, (u_char **) dkim->dkim_libhandle->dkiml_requiredhdrs, TRUE)) return DKIM_STAT_INVALID; if (!dkim_hdrlist((u_char *) buf, sizeof buf, (u_char **) hdrlist, FALSE)) return DKIM_STAT_INVALID; if (strlcat(buf, ")$", sizeof buf) >= sizeof buf) return DKIM_STAT_INVALID; status = regcomp(dkim->dkim_hdrre, buf, (REG_EXTENDED|REG_ICASE)); if (status != 0) return DKIM_STAT_INTERNAL; } return DKIM_STAT_OK; } /* ** DKIM_SIG_GETSSLBUF -- get the SSL error buffer, if any ** ** Parameters: ** sig -- signature whose buffer should be retrieved ** ** Return value: ** Pointer to the string, if defined, or NULL otherwise. */ const char * dkim_sig_getsslbuf(DKIM_SIGINFO *sig) { assert(sig != NULL); if (sig->sig_sslerrbuf != NULL) return dkim_dstring_get(sig->sig_sslerrbuf); else return NULL; } /* ** DKIM_GETSSLBUF -- get the SSL error buffer, if any ** ** Parameters: ** dkim -- DKIM handle from which to get SSL error ** ** Return value: ** Pointer to the string, if defined, or NULL otherwise. */ const char * dkim_getsslbuf(DKIM *dkim) { assert(dkim != NULL); if (dkim->dkim_sslerrbuf != NULL) return dkim_dstring_get(dkim->dkim_sslerrbuf); else return NULL; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/dkim.h000066400000000000000000001513551337314105200220610ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, 2018, The Trusted Domain Project. ** All rights reserved. */ #ifndef _DKIM_H_ #define _DKIM_H_ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* system includes */ #include #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #ifdef HAVE_LIMITS_H # include #endif /* HAVE_LIMITS_H */ /* ** version -- 0xrrMMmmpp ** ** rr == release number ** MM == major revision number ** mm == minor revision number ** pp == patch number */ #define OPENDKIM_LIB_VERSION 0x020B0000 #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* definitions */ #define DKIM_ATPSTAG "atps" /* ATPS tag name */ #define DKIM_ATPSHTAG "atpsh" /* ATPS tag name */ #define DKIM_HDRMARGIN 75 /* "standard" header margin */ #define DKIM_MAXHEADER 4096 /* buffer for caching one header */ #define DKIM_MAXHOSTNAMELEN 256 /* max. FQDN we support */ #define DKIM_REPORTTAG "r" /* DKIM reporting request tag */ #define DKIM_REPORTTAGVAL "y" /* DKIM reporting request tag value */ #define DKIM_SIGNHEADER "DKIM-Signature" /* DKIM signature header */ /* special DNS tokens */ #define DKIM_DNSKEYNAME "_domainkey" /* reserved DNS sub-zone */ /* macros */ #define DKIM_SIG_CHECK(x) ((dkim_sig_getflags((x)) & DKIM_SIGFLAG_PASSED) != 0 && dkim_sig_getbh((x)) == DKIM_SIGBH_MATCH) /* ** DKIM_STAT -- status code type */ typedef int DKIM_STAT; #define DKIM_STAT_OK 0 /* function completed successfully */ #define DKIM_STAT_BADSIG 1 /* signature available but failed */ #define DKIM_STAT_NOSIG 2 /* no signature available */ #define DKIM_STAT_NOKEY 3 /* public key not found */ #define DKIM_STAT_CANTVRFY 4 /* can't get domain key to verify */ #define DKIM_STAT_SYNTAX 5 /* message is not valid syntax */ #define DKIM_STAT_NORESOURCE 6 /* resource unavailable */ #define DKIM_STAT_INTERNAL 7 /* internal error */ #define DKIM_STAT_REVOKED 8 /* key found, but revoked */ #define DKIM_STAT_INVALID 9 /* invalid function parameter */ #define DKIM_STAT_NOTIMPLEMENT 10 /* function not implemented */ #define DKIM_STAT_KEYFAIL 11 /* key retrieval failed */ #define DKIM_STAT_CBREJECT 12 /* callback requested reject */ #define DKIM_STAT_CBINVALID 13 /* callback gave invalid result */ #define DKIM_STAT_CBTRYAGAIN 14 /* callback says try again later */ #define DKIM_STAT_CBERROR 15 /* callback error */ #define DKIM_STAT_MULTIDNSREPLY 16 /* multiple DNS replies */ #define DKIM_STAT_SIGGEN 17 /* signature generation failed */ /* ** DKIM_CBSTAT -- callback status code type */ typedef int DKIM_CBSTAT; #define DKIM_CBSTAT_CONTINUE 0 /* continue */ #define DKIM_CBSTAT_REJECT 1 /* reject */ #define DKIM_CBSTAT_TRYAGAIN 2 /* try again later */ #define DKIM_CBSTAT_NOTFOUND 3 /* requested record not found */ #define DKIM_CBSTAT_ERROR 4 /* error requesting record */ #define DKIM_CBSTAT_DEFAULT 5 /* bypass; use default handling */ /* ** DKIM_SIGERROR -- signature errors */ typedef int DKIM_SIGERROR; #define DKIM_SIGERROR_UNKNOWN (-1) /* unknown error */ #define DKIM_SIGERROR_OK 0 /* no error */ #define DKIM_SIGERROR_VERSION 1 /* unsupported version */ #define DKIM_SIGERROR_DOMAIN 2 /* invalid domain (d=/i=) */ #define DKIM_SIGERROR_EXPIRED 3 /* signature expired */ #define DKIM_SIGERROR_FUTURE 4 /* signature in the future */ #define DKIM_SIGERROR_TIMESTAMPS 5 /* x= < t= */ #define DKIM_SIGERROR_UNUSED 6 /* OBSOLETE */ #define DKIM_SIGERROR_INVALID_HC 7 /* c= invalid (header) */ #define DKIM_SIGERROR_INVALID_BC 8 /* c= invalid (body) */ #define DKIM_SIGERROR_MISSING_A 9 /* a= missing */ #define DKIM_SIGERROR_INVALID_A 10 /* a= invalid */ #define DKIM_SIGERROR_MISSING_H 11 /* h= missing */ #define DKIM_SIGERROR_INVALID_L 12 /* l= invalid */ #define DKIM_SIGERROR_INVALID_Q 13 /* q= invalid */ #define DKIM_SIGERROR_INVALID_QO 14 /* q= option invalid */ #define DKIM_SIGERROR_MISSING_D 15 /* d= missing */ #define DKIM_SIGERROR_EMPTY_D 16 /* d= empty */ #define DKIM_SIGERROR_MISSING_S 17 /* s= missing */ #define DKIM_SIGERROR_EMPTY_S 18 /* s= empty */ #define DKIM_SIGERROR_MISSING_B 19 /* b= missing */ #define DKIM_SIGERROR_EMPTY_B 20 /* b= empty */ #define DKIM_SIGERROR_CORRUPT_B 21 /* b= corrupt */ #define DKIM_SIGERROR_NOKEY 22 /* no key found in DNS */ #define DKIM_SIGERROR_DNSSYNTAX 23 /* DNS reply corrupt */ #define DKIM_SIGERROR_KEYFAIL 24 /* DNS query failed */ #define DKIM_SIGERROR_MISSING_BH 25 /* bh= missing */ #define DKIM_SIGERROR_EMPTY_BH 26 /* bh= empty */ #define DKIM_SIGERROR_CORRUPT_BH 27 /* bh= corrupt */ #define DKIM_SIGERROR_BADSIG 28 /* signature mismatch */ #define DKIM_SIGERROR_SUBDOMAIN 29 /* unauthorized subdomain */ #define DKIM_SIGERROR_MULTIREPLY 30 /* multiple records returned */ #define DKIM_SIGERROR_EMPTY_H 31 /* h= empty */ #define DKIM_SIGERROR_INVALID_H 32 /* h= missing req'd entries */ #define DKIM_SIGERROR_TOOLARGE_L 33 /* l= value exceeds body size */ #define DKIM_SIGERROR_MBSFAILED 34 /* "must be signed" failure */ #define DKIM_SIGERROR_KEYVERSION 35 /* unknown key version */ #define DKIM_SIGERROR_KEYUNKNOWNHASH 36 /* unknown key hash */ #define DKIM_SIGERROR_KEYHASHMISMATCH 37 /* sig-key hash mismatch */ #define DKIM_SIGERROR_NOTEMAILKEY 38 /* not an e-mail key */ #define DKIM_SIGERROR_UNUSED2 39 /* OBSOLETE */ #define DKIM_SIGERROR_KEYTYPEMISSING 40 /* key type missing */ #define DKIM_SIGERROR_KEYTYPEUNKNOWN 41 /* key type unknown */ #define DKIM_SIGERROR_KEYREVOKED 42 /* key revoked */ #define DKIM_SIGERROR_KEYDECODE 43 /* key couldn't be decoded */ #define DKIM_SIGERROR_MISSING_V 44 /* v= tag missing */ #define DKIM_SIGERROR_EMPTY_V 45 /* v= tag empty */ #define DKIM_SIGERROR_KEYTOOSMALL 46 /* too few key bits */ #define DKIM_SIGERROR_CONDITIONAL 47 /* conditional sig error */ #define DKIM_SIGERROR_CONDLOOP 48 /* conditional sig loop */ /* generic DNS error codes */ #define DKIM_DNS_ERROR (-1) /* error in transit */ #define DKIM_DNS_SUCCESS 0 /* reply available */ #define DKIM_DNS_NOREPLY 1 /* reply not available (yet) */ #define DKIM_DNS_EXPIRED 2 /* no reply, query expired */ #define DKIM_DNS_INVALID 3 /* invalid request */ /* ** DKIM_CANON -- canonicalization method */ typedef int dkim_canon_t; #define DKIM_CANON_UNKNOWN (-1) /* unknown method */ #define DKIM_CANON_SIMPLE 0 /* as specified in DKIM spec */ #define DKIM_CANON_RELAXED 1 /* as specified in DKIM spec */ #define DKIM_CANON_DEFAULT DKIM_CANON_SIMPLE /* ** DKIM_SIGN -- signing method */ typedef int dkim_alg_t; #define DKIM_SIGN_UNKNOWN (-2) /* unknown method */ #define DKIM_SIGN_DEFAULT (-1) /* use internal default */ #define DKIM_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */ #define DKIM_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */ #define DKIM_SIGN_ED25519SHA256 2 /* an ED25519-signed SHA256 digest */ /* ** DKIM_QUERY -- query method */ typedef int dkim_query_t; #define DKIM_QUERY_UNKNOWN (-1) /* unknown method */ #define DKIM_QUERY_DNS 0 /* DNS query method (per the draft) */ #define DKIM_QUERY_FILE 1 /* text file method (for testing) */ #define DKIM_QUERY_DEFAULT DKIM_QUERY_DNS /* ** DKIM_PARAM -- known signature parameters */ typedef int dkim_param_t; #define DKIM_PARAM_UNKNOWN (-1) /* unknown */ #define DKIM_PARAM_SIGNATURE 0 /* b */ #define DKIM_PARAM_SIGNALG 1 /* a */ #define DKIM_PARAM_DOMAIN 2 /* d */ #define DKIM_PARAM_CANONALG 3 /* c */ #define DKIM_PARAM_QUERYMETHOD 4 /* q */ #define DKIM_PARAM_SELECTOR 5 /* s */ #define DKIM_PARAM_HDRLIST 6 /* h */ #define DKIM_PARAM_VERSION 7 /* v */ #define DKIM_PARAM_IDENTITY 8 /* i */ #define DKIM_PARAM_TIMESTAMP 9 /* t */ #define DKIM_PARAM_EXPIRATION 10 /* x */ #define DKIM_PARAM_COPIEDHDRS 11 /* z */ #define DKIM_PARAM_BODYHASH 12 /* bh */ #define DKIM_PARAM_BODYLENGTH 13 /* l */ /* ** DKIM_MODE -- mode of a handle */ #define DKIM_MODE_UNKNOWN (-1) #define DKIM_MODE_SIGN 0 #define DKIM_MODE_VERIFY 1 /* ** DKIM_OPTS -- library-specific options */ typedef int dkim_opt_t; #define DKIM_OP_GETOPT 0 #define DKIM_OP_SETOPT 1 typedef int dkim_opts_t; #define DKIM_OPTS_FLAGS 0 #define DKIM_OPTS_TMPDIR 1 #define DKIM_OPTS_TIMEOUT 2 #define DKIM_OPTS_SENDERHDRS 3 /* obsolete */ #define DKIM_OPTS_SIGNHDRS 4 #define DKIM_OPTS_OVERSIGNHDRS 5 #define DKIM_OPTS_QUERYMETHOD 6 #define DKIM_OPTS_QUERYINFO 7 #define DKIM_OPTS_FIXEDTIME 8 #define DKIM_OPTS_SKIPHDRS 9 #define DKIM_OPTS_ALWAYSHDRS 10 /* obsolete */ #define DKIM_OPTS_SIGNATURETTL 11 #define DKIM_OPTS_CLOCKDRIFT 12 #define DKIM_OPTS_MUSTBESIGNED 13 #define DKIM_OPTS_MINKEYBITS 14 #define DKIM_OPTS_REQUIREDHDRS 15 #define DKIM_LIBFLAGS_NONE 0x00000000 #define DKIM_LIBFLAGS_TMPFILES 0x00000001 #define DKIM_LIBFLAGS_KEEPFILES 0x00000002 #define DKIM_LIBFLAGS_SIGNLEN 0x00000004 #define DKIM_LIBFLAGS_CACHE 0x00000008 #define DKIM_LIBFLAGS_ZTAGS 0x00000010 #define DKIM_LIBFLAGS_DELAYSIGPROC 0x00000020 #define DKIM_LIBFLAGS_EOHCHECK 0x00000040 #define DKIM_LIBFLAGS_ACCEPTV05 0x00000080 #define DKIM_LIBFLAGS_FIXCRLF 0x00000100 #define DKIM_LIBFLAGS_ACCEPTDK 0x00000200 #define DKIM_LIBFLAGS_BADSIGHANDLES 0x00000400 #define DKIM_LIBFLAGS_VERIFYONE 0x00000800 #define DKIM_LIBFLAGS_STRICTHDRS 0x00001000 #define DKIM_LIBFLAGS_REPORTBADADSP 0x00002000 #define DKIM_LIBFLAGS_DROPSIGNER 0x00004000 #define DKIM_LIBFLAGS_STRICTRESIGN 0x00008000 #define DKIM_LIBFLAGS_REQUESTREPORTS 0x00010000 #define DKIM_LIBFLAGS_DEFAULT DKIM_LIBFLAGS_NONE /* ** DKIM_DNSSEC -- results of DNSSEC queries */ #define DKIM_DNSSEC_UNKNOWN (-1) #define DKIM_DNSSEC_BOGUS 0 #define DKIM_DNSSEC_INSECURE 1 #define DKIM_DNSSEC_SECURE 2 /* ** DKIM_ATPS -- ATPS result codes */ #define DKIM_ATPS_UNKNOWN (-1) #define DKIM_ATPS_NOTFOUND 0 #define DKIM_ATPS_FOUND 1 typedef int dkim_atps_t; /* ** DKIM_LIB -- library handle */ struct dkim_lib; typedef struct dkim_lib DKIM_LIB; /* ** DKIM -- DKIM context */ struct dkim; typedef struct dkim DKIM; /* ** DKIM_SIGKEY_T -- private/public key (unencoded) */ typedef unsigned char * dkim_sigkey_t; /* ** DKIM_SIGINFO -- signature information for use by the caller */ struct dkim_siginfo; typedef struct dkim_siginfo DKIM_SIGINFO; #define DKIM_SIGFLAG_IGNORE 0x01 #define DKIM_SIGFLAG_PROCESSED 0x02 #define DKIM_SIGFLAG_PASSED 0x04 #define DKIM_SIGFLAG_TESTKEY 0x08 #define DKIM_SIGFLAG_NOSUBDOMAIN 0x10 #define DKIM_SIGFLAG_KEYLOADED 0x20 #define DKIM_SIGBH_UNTESTED (-1) #define DKIM_SIGBH_MATCH 0 #define DKIM_SIGBH_MISMATCH 1 /* ** DKIM_QUERYINFO -- information about a DNS query that is/may be needed */ struct dkim_queryinfo; typedef struct dkim_queryinfo DKIM_QUERYINFO; /* ** DKIM_HDRDIFF -- header differences */ struct dkim_hdrdiff { u_char * hd_old; u_char * hd_new; }; /* ** PROTOTYPES */ /* ** DKIM_INIT -- initialize the DKIM package ** ** Parameters: ** mallocf -- a function to receive malloc()-like calls, or NULL ** freef -- a function to receive corresponding free()-like calls, or NULL ** ** Return value: ** A new DKIM library instance handle, or NULL on failure. */ extern DKIM_LIB *dkim_init __P((void *(*mallocf)(void *closure, size_t nbytes), void (*freef)(void *closure, void *p))); /* ** DKIM_CLOSE -- shut down the DKIM package ** ** Parameters: ** lib -- DKIM_LIB handle to shut down ** ** Return value: ** None. */ extern void dkim_close __P((DKIM_LIB *lib)); /* ** DKIM_SIGN -- make a new DKIM context for signing ** ** Parameters: ** libhandle -- library handle, returned by dkim_init() ** id -- an opaque printable string for identifying this message, suitable ** for use in logging or debug output; may not be NULL ** memclosure -- memory closure, for use by user-provided malloc/free ** secretkey -- pointer to secret key data to use; if NULL, it will be ** obtained from disk ** selector -- selector being used to sign ** domain -- domain on behalf of which we're signing ** hdr_canon_alg -- canonicalization algorithm to use for headers; ** one of the DKIM_CANON_* macros, or -1 for default ** body_canon_alg -- canonicalization algorithm to use for body; ** one of the DKIM_CANON_* macros, or -1 for default ** sign_alg -- signing algorithm to use; one of the DKIM_SIGN_* macros, ** or -1 for default ** length -- number of bytes of the body to sign (-1 == all) ** statp -- pointer to a DKIM_STAT which is updated by this call ** ** Return value: ** A newly-allocated DKIM handle, or NULL on failure. "statp" will be ** updated. */ extern DKIM *dkim_sign __P((DKIM_LIB *libhandle, const unsigned char *id, void *memclosure, const dkim_sigkey_t secretkey, const unsigned char *selector, const unsigned char *domain, dkim_canon_t hdr_canon_alg, dkim_canon_t body_canon_alg, dkim_alg_t sign_alg, ssize_t length, DKIM_STAT *statp)); /* ** DKIM_VERIFY -- make a new DKIM context for verifying ** ** Parameters: ** libhandle -- library handle, returned by dkim_init() ** id -- an opaque printable string for identifying this message, suitable ** for use in logging or debug output; may not be NULL ** memclosure -- memory closure, for use by user-provided malloc/free ** statp -- pointer to a DKIM_STAT which is updated by this call ** ** Return value: ** A newly-allocated DKIM handle, or NULL on failure. "statp" will be ** updated. */ extern DKIM *dkim_verify __P((DKIM_LIB *libhandle, const unsigned char *id, void *memclosure, DKIM_STAT *statp)); /* ** DKIM_RESIGN -- bind a new signing handle to a verifying handle ** ** Parameters: ** new -- new signing handle ** old -- old signing/verifying handle ** hdrbind -- bind headers as well as body ** ** Return value: ** DKIM_STAT_OK -- success ** DKIM_STAT_INVALID -- invalid state of one or both handles ** DKIM_STAT_NOTIMPLEMENT -- not enabled at compile-time ** ** Side effects: ** Sets up flags such that the two are bound; dkim_free() on "old" ** now does nothing, and dkim_free() on "new" will free "old" once ** its reference count reaches zero. See documentation for details. */ extern DKIM_STAT dkim_resign __P((DKIM *news, DKIM *olds, _Bool hdrbind)); /* ** DKIM_HEADER -- process a header ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() or ** dkim_verify() ** hdr -- the header to be processed, in canonical format ** len -- number of bytes to process starting at "hdr" ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_header __P((DKIM *dkim, u_char *hdr, size_t len)); /* ** DKIM_EOH -- identify end of headers ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() or ** dkim_verify() ** ** Return value: ** A DKIM_STAT value. DKIM_STAT_NOSIG will be returned if we're ** validating a signature but no DKIM signature was found in the headers. */ extern DKIM_STAT dkim_eoh __P((DKIM *dkim)); /* ** DKIM_BODY -- process a body chunk ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() or ** dkim_verify() ** buf -- the body chunk to be processed, in canonical format ** len -- number of bytes to process starting at "hdr" ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_body __P((DKIM *dkim, u_char *buf, size_t len)); /* ** DKIM_CHUNK -- process a message chunk ** ** Parameters: ** dkim -- DKIM handle ** buf -- data to process ** buflen -- number of bytes at "buf" to process ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_chunk __P((DKIM *dkim, u_char *buf, size_t buflen)); /* ** DKIM_EOM -- identify end of body ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() or ** dkim_verify() ** testkey -- TRUE iff the a matching key was found but is marked as a ** test key (returned) ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_eom __P((DKIM *dkim, _Bool *testkey)); /* ** DKIM_KEY_SYNTAX -- process a key record parameter set for valid syntax ** ** Parameters: ** dkim -- DKIM context in which this is performed ** str -- string to be scanned ** len -- number of bytes available at "str" ** ** Return value: ** A DKIM_STAT constant. */ extern DKIM_STAT dkim_key_syntax __P((DKIM *dkim, u_char *str, size_t len)); /* ** DKIM_SIG_SYNTAX -- process a signature parameter set for valid syntax ** ** Parameters: ** dkim -- DKIM context in which this is performed ** str -- string to be scanned ** len -- number of bytes available at "str" ** ** Return value: ** A DKIM_STAT constant. */ extern DKIM_STAT dkim_sig_syntax __P((DKIM *dkim, u_char *str, size_t len)); /* ** DKIM_GETID -- retrieve "id" pointer from a handle ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** The "id" pointer from inside the handle, stored when it was created. */ extern const char *dkim_getid __P((DKIM *dkim)); /* ** DKIM_GETCACHESTATS -- retrieve cache statistics ** ** Parameters: ** lib -- DKIM library handle ** queries -- number of queries handled (returned) ** hits -- number of cache hits (returned) ** expired -- number of expired hits (returned) ** reset -- if true, reset the queries, hits, and expired counters ** ** Return value: ** DKIM_STAT_OK -- statistics returned ** DKIM_STAT_INVALID -- cache not initialized ** DKIM_STAT_NOTIMPLEMENT -- function not implemented ** ** Notes: ** Any of the parameters may be NULL if the corresponding datum ** is not of interest. */ extern DKIM_STAT dkim_getcachestats __P((DKIM_LIB *, u_int *queries, u_int *hits, u_int *expired, u_int *keys, _Bool reset)); /* ** DKIM_FLUSH_CACHE -- purge expired records from the database, reclaiming ** space for use by new data ** ** Parameters: ** lib -- DKIM library whose cache should be flushed ** ** Return value: ** -1 -- caching is not in effect ** >= 0 -- number of flushed records */ extern int dkim_flush_cache __P((DKIM_LIB *lib)); /* ** DKIM_MINBODY -- return number of bytes still expected ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** 0 -- all canonicalizations satisfied ** ULONG_MAX -- at least one canonicalization wants the whole message ** other -- bytes required to satisfy all canonicalizations */ extern u_long dkim_minbody __P((DKIM *dkim)); /* ** DKIM_GETSIGLIST -- retrieve the list of signatures ** ** Parameters: ** dkim -- DKIM handle ** sigs -- pointer to a vector of DKIM_SIGINFO pointers (updated) ** nsigs -- pointer to an integer to receive the pointer count (updated) ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_getsiglist __P((DKIM *dkim, DKIM_SIGINFO ***sigs, int *nsigs)); /* ** DKIM_GETSIGNATURE -- retrieve the "final" signature ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to a DKIM_SIGINFO handle which is the one libopendkim will ** use to return a "final" result; NULL if none could be determined. */ extern DKIM_SIGINFO *dkim_getsignature __P((DKIM *dkim)); /* ** DKIM_GETSIGHDR -- compute and return a signature header for a message ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() ** buf -- buffer into which to write the signature ** len -- number of bytes available at "buf" ** initial -- width of the first line ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_getsighdr __P((DKIM *dkim, u_char *buf, size_t len, size_t initial)); /* ** DKIM_GETSIGHDR_D -- compute and return a signature header for a message, ** but do it dynamically ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() ** initial -- width of the first line ** buf -- location of generated header (returned) ** len -- number of bytes available at "buf" (returned) ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_getsighdr_d __P((DKIM *dkim, size_t initial, u_char **buf, size_t *len)); /* ** DKIM_SIG_HDRSIGNED -- retrieve the header list from a signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** hdr -- header name to find ** ** Return value: ** TRUE iff "sig" had a header list in it and the header "hdr" ** appeared in that list. */ extern _Bool dkim_sig_hdrsigned __P((DKIM_SIGINFO *sig, u_char *hdr)); /* ** DKIM_SIG_GETQUERIES -- retrieve the queries needed to validate a signature ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** qi -- DKIM_QUERYINFO handle array (returned) ** nqi -- number of entries in the "qi" array ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_sig_getqueries __P((DKIM *dkim, DKIM_SIGINFO *sig, DKIM_QUERYINFO ***qi, unsigned int *nqi)); /* ** DKIM_SIG_GETDNSSEC -- retrieve DNSSEC results for a signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** A DKIM_DNSSEC_* constant. */ extern int dkim_sig_getdnssec __P((DKIM_SIGINFO *sig)); /* ** DKIM_SIG_SETDNSSEC -- set DNSSEC results for a signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** dnssec_status -- A DKIM_DNSSEC_* constant */ extern void dkim_sig_setdnssec __P((DKIM_SIGINFO *sig, int dnssec_status)); /* ** DKIM_SIG_GETREPORTINFO -- retrieve reporting information from a key ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** hfd -- canonicalized header descriptor (or NULL) (returned) ** bfd -- canonicalized body descriptor (or NULL) (returned) ** addr -- address buffer (or NULL) ** addrlen -- size of addr ** opts -- options buffer (or NULL) ** optslen -- size of opts ** smtp -- SMTP prefix buffer (or NULL) ** smtplen -- size of smtp ** interval -- requested report interval (or NULL) ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_sig_getreportinfo __P((DKIM *dkim, DKIM_SIGINFO *sig, int *hfd, int *bfd, u_char *addr, size_t addrlen, u_char *opts, size_t optslen, u_char *smtp, size_t smtplen, u_int *interval)); /* ** DKIM_SIG_GETIDENTITY -- retrieve identity of the signer ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle (or NULL to choose final one) ** val -- destination buffer ** vallen -- size of destination buffer ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_sig_getidentity __P((DKIM *dkim, DKIM_SIGINFO *sig, u_char *val, size_t vallen)); /* ** DKIM_SIG_GETCANONLEN -- report number of (canonicalized) body bytes that ** were signed ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() or ** dkim_verify() ** sig -- a DKIM_SIGINFO handle ** msglen -- total size of the message body (returned) ** canonlen -- total number of canonicalized bytes (returned) ** signlen -- restricted signature length (returned) ** ** Return value: ** A DKIM_STAT value. ** ** Notes: ** msglen or canonlen can be NULL if that information is not of interest ** to the caller. */ extern DKIM_STAT dkim_sig_getcanonlen __P((DKIM *dkim, DKIM_SIGINFO *sig, ssize_t *msglen, ssize_t *canonlen, ssize_t *signlen)); /* ** DKIM_OPTIONS -- set/get options ** ** Parameters: ** dkimlib -- DKIM library handle ** op -- operation (DKIM_OP_GET or DKIM_OP_SET) ** opt -- which option (a DKIM_OPTS_* constant) ** ptr -- value (in or out) ** len -- bytes available at "ptr" ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_options __P((DKIM_LIB *dkimlib, int op, dkim_opts_t opt, void *ptr, size_t len)); /* ** DKIM_SIG_GETFLAGS -- retreive signature handle flags ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** An unsigned integer which is a bitwise-OR of the DKIM_SIGFLAG_* ** constants currently set in the provided handle. */ extern unsigned int dkim_sig_getflags __P((DKIM_SIGINFO *sig)); /* ** DKIM_SIG_GETBH -- retreive signature handle "bh" test state ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** An integer that is one of the DKIM_SIGBH_* constants ** indicating the current state of "bh" evaluation of the signature. */ extern int dkim_sig_getbh __P((DKIM_SIGINFO *sig)); /* ** DKIM_SIG_GETKEYSIZE -- retreive key size after verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** bits -- size of the key in bits (returned) ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_sig_getkeysize __P((DKIM_SIGINFO *sig, unsigned int *bits)); /* ** DKIM_SIG_GETSIGNALG -- retreive signature algorithm after verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** alg -- a DKIM_SIGN_* value (returned) ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_sig_getsignalg __P((DKIM_SIGINFO *sig, dkim_alg_t *alg)); /* ** DKIM_SIG_GETSIGNTIME -- retreive signature timestamp after verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** when -- timestamp on the signature (returned) ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_sig_getsigntime __P((DKIM_SIGINFO *sig, uint64_t *when)); /* ** DKIM_SIG_GETSELECTOR -- retrieve selector used to generate the signature ** ** Parameters: ** sig -- DKIM_SIGINFO handle from which to retrieve selector ** ** Return value: ** Selector found in the signature. */ extern unsigned char *dkim_sig_getselector __P((DKIM_SIGINFO *sig)); /* ** DKIM_SIG_GETDOMAIN -- retrieve signing domain after verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** Pointer to the signing domain. */ extern unsigned char *dkim_sig_getdomain __P((DKIM_SIGINFO *sig)); /* ** DKIM_SIG_GETALGORITHM -- retrieve algorithm from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO from which to extract the ** algorithm ** ** Return value: ** Pointer to the algorithm associated with the DKIM_SIGINFO. */ extern unsigned char *dkim_sig_getalgorithm __P((DKIM_SIGINFO *sig)); /* ** DKIM_SIG_GETCANONS -- retrieve canonicaliztions after verifying ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** ** Return value: ** DKIM_STAT_OK -- success */ extern DKIM_STAT dkim_sig_getcanons __P((DKIM_SIGINFO *sig, dkim_canon_t *hdr, dkim_canon_t *body)); /* ** DKIM_SET_USER_CONTEXT -- set DKIM handle user context ** ** Parameters: ** dkim -- DKIM signing handle ** ctx -- user context pointer to store ** ** Parameters: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_set_user_context __P((DKIM *dkim, void *ctx)); /* ** DKIM_GET_USER_CONTEXT -- retrieve DKIM handle user context ** ** Parameters: ** dkim -- DKIM signing handle ** ** Parameters: ** User context pointer. */ extern void *dkim_get_user_context __P((DKIM *dkim)); /* ** DKIM_GETMODE -- return the mode (signing, verifying, etc.) of a handle ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** A DKIM_MODE_* constant. */ extern int dkim_getmode __P((DKIM *dkim)); /* ** DKIM_GETDOMAIN -- retrieve policy domain from a DKIM context ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to the domain used for policy checking (if any) or NULL if ** no domain could be determined. */ extern u_char *dkim_getdomain __P((DKIM *dkim)); /* ** DKIM_GETUSER -- retrieve sending user (local-part) from a DKIM context ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** Pointer to the apparent sending user (local-part) or NULL if not known. */ extern u_char *dkim_getuser __P((DKIM *dkim)); /* ** DKIM_GET_SIGNER -- get DKIM signature's signer ** ** Parameters: ** dkim -- DKIM signing handle ** ** Parameters: ** Pointer to a buffer containing the signer previously requested, ** or NULL if none. */ extern const unsigned char *dkim_get_signer __P((DKIM *dkim)); /* ** DKIM_SET_SIGNER -- set DKIM signature's signer ** ** Parameters: ** dkim -- DKIM signing handle ** signer -- signer to store ** ** Parameters: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_set_signer __P((DKIM *dkim, const u_char *signer)); /* ** DKIM_SET_DNS_CALLBACK -- set the DNS wait callback ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call; should take an opaque context pointer ** interval -- how often to call back ** ** Return value: ** DKIM_STAT_OK -- success ** DKIM_STAT_INVALID -- invalid use ** DKIM_STAT_NOTIMPLEMENT -- underlying resolver doesn't support callbacks */ extern DKIM_STAT dkim_set_dns_callback __P((DKIM_LIB *libopendkim, void (*func)(const void *context), unsigned int interval)); /* ** DKIM_SET_KEY_LOOKUP -- set the key lookup function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ extern DKIM_STAT dkim_set_key_lookup __P((DKIM_LIB *libopendkim, DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO *sig, u_char *buf, size_t buflen))); /* ** DKIM_SET_SIGNATURE_HANDLE -- set the signature handle creator function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** Pointer to the user-side handle thus created, or NULL. */ extern DKIM_STAT dkim_set_signature_handle __P((DKIM_LIB *libopendkim, void * (*func)(void *closure))); /* ** DKIM_SET_SIGNATURE_HANDLE_FREE -- set the signature handle destroyer ** function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** None. */ extern DKIM_STAT dkim_set_signature_handle_free __P((DKIM_LIB *libopendkim, void (*func)(void *closure, void *user))); /* ** DKIM_SET_SIGNATURE_TAGVALUES -- set the signature handle populator function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ extern DKIM_STAT dkim_set_signature_tagvalues __P((DKIM_LIB *libopendkim, void (*func)(void *user, dkim_param_t pcode, const u_char *param, const u_char *value))); /* ** DKIM_SET_PRESCREEN -- set the prescreen function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ extern DKIM_STAT dkim_set_prescreen __P((DKIM_LIB *libopendkim, DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs))); /* ** DKIM_SET_FINAL -- set the final processing function ** ** Parameters: ** libopendkim -- DKIM library handle ** func -- function to call ** ** Return value: ** DKIM_STAT_OK */ extern DKIM_STAT dkim_set_final __P((DKIM_LIB *libopendkim, DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs))); /* ** DKIM_SIG_GETCONTEXT -- get user-specific context from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- a pointer to a DKIM_SIGINFO ** ** Return value: ** The user-provided pointer stored in the named "siginfo", or NULL ** if none was ever set. */ extern void *dkim_sig_getcontext __P((DKIM_SIGINFO *siginfo)); /* ** DKIM_SIG_GETERROR -- get error code from a DKIM_SIGINFO ** ** Parameters: ** siginfo -- a pointer to a DKIM_SIGINFO ** ** Return value: ** A DKIM_SIGERROR_* constant. */ extern int dkim_sig_geterror __P((DKIM_SIGINFO *siginfo)); /* ** DKIM_SIG_SETERROR -- set error code in a DKIM_SIGINFO ** ** Parameters: ** siginfo -- a pointer to a DKIM_SIGINFO ** err -- error code ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_sig_seterror __P((DKIM_SIGINFO *siginfo, int err)); /* ** DKIM_SIG_GETERRORSTR -- translate a DKIM_SIGERROR into a string ** ** Parameters: ** sigerr -- a DKIM_SIGERROR constant ** ** Return value: ** A pointer to a human-readable string translation of "sigerr", or NULL ** if no such translation exists. */ extern const char *dkim_sig_geterrorstr __P((DKIM_SIGERROR sigerr)); /* ** DKIM_SIG_IGNORE -- mark a signature referenced by a DKIM_SIGINFO with ** an "ignore" flag ** ** Parameters: ** siginfo -- pointer to a DKIM_SIGINFO to update ** ** Return value: ** None. */ extern void dkim_sig_ignore __P((DKIM_SIGINFO *siginfo)); /* ** DKIM_SIG_PROCESS -- process a signature ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_sig_process __P((DKIM *dkim, DKIM_SIGINFO *sig)); /* ** DKIM_FREE -- release resources associated with a DKIM handle ** ** Parameters: ** dkim -- a DKIM handle previously returned by dkim_sign() or ** dkim_verify() ** ** Return value: ** A DKIM_STAT value. */ extern DKIM_STAT dkim_free __P((DKIM *dkim)); /* ** DKIM_GETERROR -- return any stored error string from within the DKIM ** context handle ** ** Parameters: ** dkim -- DKIM handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ extern const char *dkim_geterror __P((DKIM *dkim)); /* ** DKIM_GETRESULTSTR -- translate a DKIM_STAT_* constant to a string ** ** Parameters: ** result -- DKIM_STAT_* constant to translate ** ** Return value: ** Pointer to a text describing "result", or NULL if none exists */ extern const char *dkim_getresultstr __P((DKIM_STAT result)); /* ** DKIM_OHDRS -- extract and decode original headers ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** ptrs -- user-provided array of pointers to header strings (updated) ** pcnt -- number of pointers available (updated) ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_ohdrs __P((DKIM *dkim, DKIM_SIGINFO *sig, u_char **ptrs, int *pcnt)); /* ** DKIM_DIFFHEADERS -- compare original headers with received headers ** ** Parameters: ** dkim -- DKIM handle ** canon -- canonicalization mode in use ** maxcost -- maximum "cost" of changes to be reported ** ohdrs -- original headers, presumably extracted from a "z" tag ** nohdrs -- number of headers at "ohdrs" available ** out -- pointer to an array of struct dkim_hdrdiff objects (updated) ** nout -- counter of handles returned (updated) ** ** Return value: ** A DKIM_STAT_* constant. ** ** Side effects: ** A series of DKIM_HDRDIFF handles is allocated and must later be ** destroyed. */ extern DKIM_STAT dkim_diffheaders __P((DKIM *dkim, dkim_canon_t canon, int maxcost, char **ohdrs, int nohdrs, struct dkim_hdrdiff **out, int *nout)); /* ** DKIM_GETPARTIAL -- return a DKIM handle's "body length tag" flag ** ** Parameters: ** dkim -- DKIM handle ** ** Return value: ** True iff the signature is to include a body length tag */ extern _Bool dkim_getpartial __P((DKIM *dkim)); /* ** DKIM_SETPARTIAL -- set the DKIM handle to sign using the DKIM body length ** tag (l=) ** ** Parameters: ** dkim -- DKIM handle ** value -- new flag value ** ** Return value: ** DKIM_STAT_OK */ extern DKIM_STAT dkim_setpartial __P((DKIM *dkim, _Bool value)); /* ** DKIM_SET_MARGIN -- set the margin to use when generating signatures ** ** Parameters: ** dkim -- DKIM handle ** value -- new margin value ** ** Return value: ** DKIM_STAT_INVALID -- "dkim" referenced a verification handle, or ** "value" was negative ** DKIM_STAT_OK -- otherwise */ extern DKIM_STAT dkim_set_margin __P((DKIM *dkim, int value)); /* ** DKIM_MAIL_PARSE -- extract the local-part and domain-name from a structured ** header field ** ** Parameters: ** addr -- the header to parse; see RFC2822 for format ** user -- local-part of the parsed header (returned) ** domain -- domain part of the parsed header (returned) ** ** Return value: ** 0 on success; other on error (see source) */ extern int dkim_mail_parse __P((u_char *addr, u_char **user, u_char **domain)); /* ** DKIM_SSL_VERSION -- return the version of the OpenSSL library against ** which this library was compiled ** ** Parameters: ** None. ** ** Return value: ** The OPENSSL_VERSION_NUMBER constant as defined by OpenSSL. */ extern unsigned long dkim_ssl_version __P((void)); /* ** DKIM_LIBFEATURE -- check for a library feature ** ** Parameters: ** lib -- DKIM_LIB handle ** fc -- feature code ** ** Return value: ** TRUE iff the library was compiled with the requested feature */ #define DKIM_FEATURE_DIFFHEADERS 0 #define DKIM_FEATURE_UNUSED 1 #define DKIM_FEATURE_PARSE_TIME 2 #define DKIM_FEATURE_QUERY_CACHE 3 #define DKIM_FEATURE_SHA256 4 #define DKIM_FEATURE_OVERSIGN 5 #define DKIM_FEATURE_DNSSEC 6 #define DKIM_FEATURE_RESIGN 7 #define DKIM_FEATURE_ATPS 8 #define DKIM_FEATURE_XTAGS 9 #define DKIM_FEATURE_CONDITIONAL 10 #define DKIM_FEATURE_ED25519 11 #define DKIM_FEATURE_MAX 11 extern _Bool dkim_libfeature __P((DKIM_LIB *lib, u_int fc)); /* ** DKIM_LIBVERSION -- return version of libopendkim at runtime ** ** Parameters: ** None. ** ** Return value: ** Library version, i.e. value of the OPENDKIM_LIB_VERSION macro. */ extern uint32_t dkim_libversion __P((void)); /* ** DKIM_GET_SIGSUBSTRING -- retrieve a minimal signature substring for ** disambiguation ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** buf -- buffer into which to put the substring ** buflen -- bytes available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_get_sigsubstring __P((DKIM *, DKIM_SIGINFO *, char *, size_t *)); /* ** DKIM_TEST_KEY -- retrieve a public key and verify it against a provided ** private key ** ** Parameters: ** lib -- DKIM library handle ** selector -- selector ** domain -- domain name ** key -- private key to verify (PEM format) ** keylen -- size of private key ** dnssec -- DNSSEC result (may be NULL) ** err -- error buffer (may be NULL) ** errlen -- size of error buffer ** ** Return value: ** 1 -- keys don't match ** 0 -- keys match (or no key provided) ** -1 -- error */ extern int dkim_test_key __P((DKIM_LIB *, char *, char *, char *, size_t, int *, char *, size_t)); /* ** DKIM_SIG_GETTAGVALUE -- retrieve a tag's value from a signature or its key ** ** Parameters: ** sig -- DKIM_SIGINFO handle ** keytag -- TRUE iff we want a key's tag ** tag -- name of the tag of interest ** ** Return value: ** Pointer to the string containing the value of the requested key, ** or NULL if not present. ** ** Notes: ** This was added for use in determining whether or not a key or ** signature contained particular data, for gathering general statistics ** about DKIM use. It is not intended to give applications direct access ** to unprocessed signature or key data. The data returned has not ** necessarily been vetted in any way. Caveat emptor. */ extern u_char *dkim_sig_gettagvalue __P((DKIM_SIGINFO *, _Bool, u_char *)); /* ** DKIM_SIG_GETSIGNEDHDRS -- retrieve the signed header fields covered by ** a signature that passed ** ** Parameters: ** dkim -- DKIM instance ** sig -- signature ** hdrs -- rectangular array of header field strings ** hdrlen -- length of each element of "hdrs" ** nhdrs -- size of "hdrs" array (updated) ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_sig_getsignedhdrs __P((DKIM *, DKIM_SIGINFO *, u_char *, size_t, u_int *)); /* ** DKIM_QP_DECODE -- decode a quoted-printable string ** ** Parameters: ** in -- input ** out -- output ** outlen -- bytes available at "out" ** ** Return value: ** >= 0 -- number of bytes in output ** -1 -- parse error */ extern int dkim_qp_decode __P((unsigned char *, unsigned char *, int)); /* ** DKIM_DNS_SET_QUERY_SERVICE -- stores a handle representing the DNS ** query service to be used, returning any ** previous handle ** ** Parameters: ** lib -- DKIM library handle ** h -- handle to be used ** ** Return value: ** Previously stored handle, or NULL if none. */ extern void *dkim_dns_set_query_service __P((DKIM_LIB *, void *)); /* ** DKIM_DNS_SET_QUERY_START -- stores a pointer to a query start function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to start queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- receives handle stored by ** dkim_dns_set_query_service() ** int type -- DNS RR query type (C_IN assumed) ** char *query -- question to ask ** char *buf -- buffer into which to write reply ** size_t buflen -- size of buf ** void **qh -- returned query handle */ extern void dkim_dns_set_query_start __P((DKIM_LIB *, int (*)(void *, int, unsigned char *, unsigned char *, size_t, void **))); /* ** DKIM_DNS_SET_QUERY_CANCEL -- stores a pointer to a query cancel function ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to cancel running queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- query handle to be canceled */ extern void dkim_dns_set_query_cancel __P((DKIM_LIB *, int (*)(void *, void *))); /* ** DKIM_DNS_SET_QUERY_WAITREPLY -- stores a pointer to wait for a DNS reply ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to wait for a reply ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- handle of query that has completed ** struct timeval *timeout -- how long to wait ** size_t *bytes -- bytes returned ** int *error -- error code returned ** int *dnssec -- DNSSEC status returned */ extern void dkim_dns_set_query_waitreply __P((DKIM_LIB *, int (*)(void *, void *, struct timeval *, size_t *, int *, int *))); /* ** DKIM_DNS_SET_INIT -- initializes the resolver ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void **srv -- DNS service handle (updated) */ extern void dkim_dns_set_init __P((DKIM_LIB *, int (*)(void **))); /* ** DKIM_DNS_SET_CLOSE -- shuts down the resolver ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to shut down the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns void ** void *srv -- DNS service handle */ extern void dkim_dns_set_close __P((DKIM_LIB *, void (*)(void *))); /* ** DKIM_DNS_SET_NSLIST -- set function that updates resolver nameserver list ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to update the nameserver list ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *srv -- DNS service handle ** const char *nslist -- nameserver list, as a comma-separated ** string */ extern void dkim_dns_set_nslist __P((DKIM_LIB *, int (*)(void *, const char *))); /* ** DKIM_DNS_SET_CONFIG -- set function that passes configuration data to ** the active resolver ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to configure the active resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *srv -- DNS service handle ** const char *config -- arbitrary configuration data */ extern void dkim_dns_set_config __P((DKIM_LIB *, int (*)(void *, const char *))); /* ** DKIM_DNS_SET_TRUSTANCHOR -- set function that passes trust anchor data to ** the active resolver ** ** Parameters: ** lib -- DKIM library handle ** func -- function to use to pass trust anchor data to the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *srv -- DNS service handle ** const char *trustanchor -- arbitrary trust anchor data */ extern void dkim_dns_set_trustanchor __P((DKIM_LIB *, int (*)(void *, const char *))); /* ** DKIM_DNS_NSLIST -- update resolver nameserver list ** ** Parameters: ** lib -- DKIM library handle ** nslist -- comma-separated nameserver list, as IP addresses ** ** Return value: ** A DKIM_DNS_* constant. ** ** Notes: ** The underlying API may not return a failure status, in which case ** this always returns DKIM_DNS_SUCCESS. The underlying API might also ** not use all of the nameservers provided. */ extern int dkim_dns_nslist __P((DKIM_LIB *, const char *)); /* ** DKIM_DNS_INIT -- force resolver (re)initialization ** ** Parameters: ** lib -- DKIM library handle ** ** Return value: ** A DKIM_DNS_* constant. */ extern int dkim_dns_init __P((DKIM_LIB *)); /* ** DKIM_DNS_CLOSE -- force resolver shutdown ** ** Parameters: ** lib -- DKIM library handle ** ** Return value: ** A DKIM_DNS_* constant. */ extern int dkim_dns_close __P((DKIM_LIB *)); /* ** DKIM_DNS_CONFIG -- requests a change to resolver configuration ** ** Parameters: ** lib -- DKIM library handle ** config -- opaque configuration string ** ** Return value: ** A DKIM_DNS_* constant. */ extern int dkim_dns_config __P((DKIM_LIB *, const char *)); /* ** DKIM_DNS_TRUSTANCHOR -- requests a change to trust anchor configuration ** ** Parameters: ** lib -- DKIM library handle ** trust -- opaque trust anchor string ** ** Return value: ** A DKIM_DNS_* constant. */ extern int dkim_dns_trustanchor __P((DKIM_LIB *, const char *)); /* ** DKIM_ADD_QUERYMETHOD -- add a query method ** ** Parameters: ** dkim -- DKIM signing handle to extend ** type -- type of query to add ** options -- options to include ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_add_querymethod __P((DKIM *, const char *, const char *)); /* ** DKIM_ADD_XTAG -- add an extension tag/value ** ** Parameters: ** dkim -- DKIM signing handle to extend ** tag -- name of tag to add ** value -- value to include ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_add_xtag __P((DKIM *, const char *, const char *)); /* ** DKIM_PRIVKEY_LOAD -- explicitly try to load the private key ** ** Parameters: ** dkim -- DKIM signing handle ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_privkey_load __P((DKIM *)); /* ** DKIM_ATPS_CHECK -- check for Authorized Third Party Signing ** ** Parameters: ** dkim -- DKIM message handle ** sig -- signature information handle ** timeout -- timeout (can be NULL) ** res -- ATPS result code ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_atps_check __P((DKIM *, DKIM_SIGINFO *, struct timeval *, dkim_atps_t *res)); /* ** DKIM_CONDITIONAL -- set conditional domain for a signature ** ** Parameters: ** dkim -- a DKIM signing handle ** domain -- domain upon which this signature shall depend ** ** Return value: ** A DKIM_STAT_* constant. */ extern DKIM_STAT dkim_conditional __P((DKIM *, u_char *)); /* ** DKIM_QI_GETNAME -- retrieve the DNS name from a DKIM_QUERYINFO object ** ** Parameters: ** query -- DKIM_QUERYINFO handle ** ** Return value: ** A pointer to a NULL-terminated string indicating the name to be ** queried, or NULL on error. */ extern const char *dkim_qi_getname __P((DKIM_QUERYINFO *)); /* ** DKIM_QI_GETTYPE -- retrieve the DNS RR type from a DKIM_QUERYINFO object ** ** Parameters: ** query -- DKIM_QUERYINFO handle ** ** Return value: ** The DNS RR type to be queried, or -1 on error. */ extern int dkim_qi_gettype __P((DKIM_QUERYINFO *)); /* ** DKIM_BASE32_ENCODE -- encode a string using base32 ** ** Parameters: ** buf -- destination buffer ** buflen -- bytes available at buf (updated) ** data -- pointer to data to encode ** size -- bytes at "data" to encode ** ** Return value: ** Length of encoding. ** ** Notes: ** buf should be at least a byte more than *buflen to hold the trailing ** '\0'. ** ** *buflen is updated to count the number of bytes read from "data". */ extern int dkim_base32_encode __P((char *, size_t *, const void *, size_t)); /* ** DKIM_SIG_GETHASHES -- retrieve hashes ** ** Parameters: ** sig -- signature from which to get completed hashes ** hh -- pointer to header hash buffer (returned) ** hhlen -- bytes used at hh (returned) ** bh -- pointer to body hash buffer (returned) ** bhlen -- bytes used at bh (returned) ** ** Return value: ** DKIM_STAT_OK -- successful completion ** DKIM_STAT_INVALID -- hashing hasn't been completed */ extern DKIM_STAT dkim_sig_gethashes __P((DKIM_SIGINFO *, void **, size_t *, void **, size_t *)); /* ** DKIM_SIGNHDRS -- set the list of header fields to sign for a signature, ** overriding the library default ** ** Parameters: ** dkim -- DKIM signing handle to be affected ** hdrlist -- array of names of header fields that should be signed ** ** Return value: ** A DKIM_STAT_* constant. ** ** Notes: ** "hdrlist" can be NULL if the library's default is to be used. */ extern DKIM_STAT dkim_signhdrs __P((DKIM *, const char **)); /* ** DKIM_GETSSLBUF -- get the SSL error buffer, if any, from a DKIM handle ** ** Parameters: ** dkim -- DKIM handle from which to get SSL error ** ** Return value: ** Pointer to the string, if defined, or NULL otherwise. */ extern const char *dkim_getsslbuf __P((DKIM *dkim)); /* ** DKIM_SIG_GETSSLBUF -- get the SSL error buffer, if any, from a signature ** ** Parameters: ** sig -- signature handle from which to get SSL error ** ** Return value: ** Pointer to the string, if defined, or NULL otherwise. */ extern const char *dkim_sig_getsslbuf __P((DKIM_SIGINFO *sig)); /* list of headers that should be signed, per RFC6376 Section 5.4 */ extern const u_char *dkim_should_signhdrs[]; /* list of headers that should not be signed, per RFC6376 Section 5.4 */ extern const u_char *dkim_should_not_signhdrs[]; #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* ! _DKIM_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/000077500000000000000000000000001337314105200217025ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/.gitignore000066400000000000000000000000251337314105200236670ustar00rootroot00000000000000Makefile Makefile.in OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/Makefile.am000066400000000000000000000054711337314105200237450ustar00rootroot00000000000000 #AUTOMAKE_OPTIONS = foreign dist_doc_DATA = dkim.html \ dkim_add_querymethod.html \ dkim_add_xtag.html \ dkim_alg_t.html \ dkim_atps_check.html \ dkim_atps_t.html \ dkim_body.html \ dkim_canon_t.html \ dkim_cbstat.html \ dkim_chunk.html \ dkim_close.html \ dkim_dns_close.html \ dkim_dns_config.html \ dkim_dns_init.html \ dkim_dns_nslist.html \ dkim_dns_set_close.html \ dkim_dns_set_config.html \ dkim_dns_set_init.html \ dkim_dns_set_nslist.html \ dkim_dns_set_query_cancel.html \ dkim_dns_set_query_service.html \ dkim_dns_set_query_start.html \ dkim_dns_set_query_waitreply.html \ dkim_dns_set_trustanchor.html \ dkim_dns_trustanchor.html \ dkim_dnssec.html \ dkim_eoh.html \ dkim_eom.html \ dkim_flush_cache.html \ dkim_free.html \ dkim_get_signer.html \ dkim_get_sigsubstring.html \ dkim_get_user_context.html \ dkim_getcachestats.html \ dkim_getdomain.html \ dkim_geterror.html \ dkim_getid.html \ dkim_getmode.html \ dkim_getresultstr.html \ dkim_getsighdr.html \ dkim_getsighdr_d.html \ dkim_getsiglist.html \ dkim_getsignature.html \ dkim_getsslbuf.html \ dkim_getuser.html \ dkim_header.html \ dkim_init.html \ dkim_key_syntax.html \ dkim_lib.html \ dkim_libfeature.html \ dkim_libversion.html \ dkim_minbody.html \ dkim_ohdrs.html \ dkim_options.html \ dkim_param_t.html \ dkim_privkey_load.html \ dkim_qi_getname.html \ dkim_qi_gettype.html \ dkim_query_t.html \ dkim_queryinfo.html \ dkim_resign.html \ dkim_set_dns_callback.html \ dkim_set_final.html \ dkim_set_key_lookup.html \ dkim_set_margin.html \ dkim_set_prescreen.html \ dkim_set_signature_handle.html \ dkim_set_signature_handle_free.html \ dkim_set_signature_tagvalues.html \ dkim_set_signer.html \ dkim_set_trust_anchor.html \ dkim_set_user_context.html \ dkim_sig_getbh.html \ dkim_sig_getcanonlen.html \ dkim_sig_getcontext.html \ dkim_sig_getdnssec.html \ dkim_sig_getdomain.html \ dkim_sig_geterror.html \ dkim_sig_geterrorstr.html \ dkim_sig_getflags.html \ dkim_sig_gethashes.html \ dkim_sig_getkeysize.html \ dkim_sig_getqueries.html \ dkim_sig_getreportinfo.html \ dkim_sig_getselector.html \ dkim_sig_getsignalg.html \ dkim_sig_getsignedhdrs.html \ dkim_sig_getsigntime.html \ dkim_sig_getsslbuf.html \ dkim_sig_gettagvalue.html \ dkim_sig_hdrsigned.html \ dkim_sig_ignore.html \ dkim_sig_process.html \ dkim_sig_seterror.html \ dkim_sig_syntax.html \ dkim_sigerror.html \ dkim_siginfo.html \ dkim_sigkey_t.html \ dkim_sign.html \ dkim_signhdrs.html \ dkim_ssl_version.html \ dkim_stat.html \ dkim_verify.html \ index.html \ overview.html \ dkim_mail_parse.html \ dkim_diffheaders.html \ dkim_get_msgdate.html \ dkim_getpartial.html \ dkim_get_reputation.html \ dkim_setpartial.html \ dkim_sig_getidentity.html \ dkim_sig_getcanons.html \ dkim_libfeature.html \ dns.html OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim.html000066400000000000000000000027101337314105200235140ustar00rootroot00000000000000 DKIM

DKIM

[back to index]

DESCRIPTION
Purpose A DKIM handle is returned by successful calls to dkim_sign() and dkim_verify(), and passed to all of the message processing functions. It contains per-message context-specific information about the message. When processing of the message is complete, it must be destroyed using a call to dkim_free().
NOTES
  • More than one DKIM handle may exist at any given time. There is no memory shared between these handles, so two different handles may be concurrently accessed in separate threads.

Copyright (c) 2005 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_add_querymethod.html000066400000000000000000000060441337314105200267560ustar00rootroot00000000000000 dkim_add_querymethod()

dkim_add_querymethod()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_add_querymethod(
	DKIM *dkim,
        const char *method,
        const char *options);
);
Requests that a signature be generated such that it requests verifiers use the specified query method and options (if any) to retrieve the verifying key. This adds the q= tag showing the specified method(s) and option(s) when the signature is generated by dkim_getsighdr(). Multiple query methods can be listed by making multiple calls to this function.
DESCRIPTION
Called When dkim_add_querymethod() can be called at any time prior to calling dkim_eom().
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign().
method A pointer to a null-terminated string that specifies the key retrieval method to be used by verifiers. This value will appear in the q= value of the generated signature.
options A pointer to a null-terminated string that specifies the query options to be used by the verifier, or NULL if no options should be shown in the signature.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- dkim referred to a verifying header rather than a signing header, or one of the provided values contained a syntax error, or a request was made to add a method or method-option pair that was already requested for the same signature
  • DKIM_STAT_NORESOURCE -- out of memory
NOTES
  • To support experimental extensions, methods not listed in RFC6376 are permitted.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_add_xtag.html000066400000000000000000000061601337314105200253520ustar00rootroot00000000000000 dkim_add_xtag()

dkim_add_xtag()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_add_xtag(
	DKIM *dkim,
        const char *tag,
        const char *value);
);
Requests that the named tag and value be added to the signature header field when it gets generated by dkim_getsighdr().
DESCRIPTION
Called When dkim_add_xtag() can be called at any time prior to calling dkim_eom().
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign().
tag A pointer to a null-terminated string that specifies the tag name to be added to the signature. This must not be a tag that is already supported by the library, as those are generated automatically. It must also meet the syntax rules of RFC6376 Section 3.2.
value A pointer to a null-terminated string that specifies the tag value to be added to the signature. It must meet the syntax rules of RFC6376 Section 3.2.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- dkim referred to a verifying header rather than a signing header, or one of the provided values contained a syntax error, or the tag named is one already supported by the library, or the named tag has already been added to the signature
  • DKIM_STAT_NORESOURCE -- out of memory
  • DKIM_STAT_NOTIMPLEMENT -- feature is not implemented for this installation
NOTES
  • It is legal to include whitespace in values according to RFC6376 Section 3.2. However, this will interefere with the automatic wrapping and formatting of the signature performed by the library. A mechanism to indicate valid line break points will be included in a future release.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_alg_t.html000066400000000000000000000033401337314105200246620ustar00rootroot00000000000000 dkim_alg_t

dkim_alg_t

[back to index]

DESCRIPTION
Purpose A dkim_alg_t is a value from an enumerated list of the possible message signing algorithms available. It is passed as a parameter to dkim_sign() when selecting a signing algorithm to be used to sign a message. It need not be passed to dkim_verify() as that function will determine the signing algorithm for verification based on the signature on an arriving message.
Possible Values
  • DKIM_SIGN_RSASHA1 -- use an RSA-signed SHA1 hash of the message's headers and body
  • DKIM_SIGN_RSASHA256 -- use an RSA-signed SHA256 hash of the message's headers and body
NOTES
  • DKIM_SIGN_RSASHA256 is only available if the OpenSSL available at compile-time supported the SHA256 algorithm.

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_atps_check.html000066400000000000000000000060111337314105200256760ustar00rootroot00000000000000 dkim_atps_check()

dkim_atps_check()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_atps_check(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
        struct timeval *timeout,
        dkim_atps_t *res
);
Perform an Authorized Third Party Signer query regarding a signature.
DESCRIPTION
Called When dkim_atps_check() is called after dkim_eom() to check for Authorized Third Party Signer status for the signing domain. This involves a DNS query to the sender's domain to ask it if the domain that signed the message is an authorized third-party signer.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_verify.
sig Signature handle naming the domain that is being tested for authorized third-party signer status.
timeout A pointer to a struct timeval that tells this call how long it should wait for a reply. A value of NULL will use the default library DNS timeout.
res A pointer to a dkim_atps_t that will receive the result of this query.
RETURN VALUES
ValueDescription
DKIM_STAT_CANTVRFY The query could not be initiated or completed.
DKIM_STAT_MULTIPLEDNSREPLY More than one reply was returned.
DKIM_STAT_OK Successful completion.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_atps_t.html000066400000000000000000000026571337314105200251000ustar00rootroot00000000000000 dkim_atps_t

dkim_atps_t

[back to index]

DESCRIPTION
Purpose A dkim_atps_t is a result from an Authorized Third-Party Signers (ATPS) check.
Possible Values
  • DKIM_ATPS_UNKNOWN -- an ATPS test has not been performed or a result could not be determined
  • DKIM_ATPS_FOUND -- the sending domain has authorized the signing domain to sign its mail
  • DKIM_ATPS_NOTFOUND -- the sending domain has not authorized the signing domain to sign its mail
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_body.html000066400000000000000000000056771337314105200245500ustar00rootroot00000000000000 dkim_body()

dkim_body()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_body(
	DKIM *dkim,
	unsigned char *bodyp,
	size_t len
);
Handle a piece of a message's body. The body block should contain normal CRLF line termination and be in canonical form (e.g., with dot-stuffing removed, if any).
DESCRIPTION
Called When dkim_body() is called zero or more times between dkim_eoh() and dkim_eom().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify()
bodyp Pointer to the start of this block of body data.
len The amount of data pointed to by bodyp.
RETURN VALUES
  • DKIM_STAT_INVALID indicates the dkim handle was rendered unusable by a previous call, likely to dkim_eoh(), or simply that dkim_eoh() has not yet been called for this handle.
  • DKIM_STAT_OK indicates normal completion.
NOTES
  • bodyp points to a sequence of bytes. It is not expected to be a C string (a sequence of characters that is terminated by '\0').
  • Dot stuffing and the terminating dot in the message body are expected to be removed by the caller. If they appear within bodyp, they are assumed to be part of the message body and will be included in the hashed data. This is true of any content modification that might be done by the MTA.

Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_canon_t.html000066400000000000000000000030201337314105200252100ustar00rootroot00000000000000 dkim_canon_t

dkim_canon_t

[back to index]

DESCRIPTION
Purpose A dkim_canon_t is a value from an enumerated list of the possible message canonicalization algorithms available. It is passed as a parameter to dkim_sign() when selecting a canonicalization algorithm to be used when preparing a message body for signing. It need not be passed to dkim_verify() as that function will determine the canonicalization algorithm for verification based on the signature on an arriving message.
Possible Values
  • DKIM_CANON_RELAXED -- "relaxed" canonicalization as defined in RFC6376
  • DKIM_CANON_SIMPLE -- "simple" canonicalization as defined in RFC6376

Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_cbstat.html000066400000000000000000000051641337314105200250620ustar00rootroot00000000000000 DKIM_CBSTAT

DKIM_CBSTAT

[back to index]

DESCRIPTION
Purpose A DKIM_CBSTAT is a return value from a callback provided to the libopendkim functions.
Possible Values
  • DKIM_CBSTAT_CONTINUE -- continue normal operation
  • DKIM_CBSTAT_ERROR -- callback encountered an error
  • DKIM_CBSTAT_NOTFOUND -- record not found
  • DKIM_CBSTAT_REJECT -- request message rejection
  • DKIM_CBSTAT_TRYAGAIN -- the callback isn't ready to complete at this time
  • DKIM_CBSTAT_DEFAULT -- bypass the callback and apply default handling
NOTES
  • DKIM_CBSTAT_CONTINUE should be returned by the callback on normal successful completion, indicating to library that normal operation should proceed
  • DKIM_CBSTAT_REJECT should be returned by the callback if the callback is able to determine that the message should be rejected; this will cause the library function which used the callback to return DKIM_STAT_CBREJECT
  • DKIM_CBSTAT_TRYAGAIN should be returned by the callback if the callback is unable to process the message at this time but a later attempt might succeed; this causes the library function which used the callback to return DKIM_STAT_CBTRYAGAIN, and the caller can re-attempt that call later
  • DKIM_CBSTAT_NOTFOUND should be returned by the callback if the record being sought was not found
  • DKIM_CBSTAT_ERROR should be returned by the callback if the attempt to retrieve the requested record returned in some kind of error
  • DKIM_CBSTAT_DEFAULT should be returned by the callback if it does not wish to return a result and instead wants the library to proceed as if the callback were not configured

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_chunk.html000066400000000000000000000111501337314105200247020ustar00rootroot00000000000000 dkim_chunk()

dkim_chunk()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_chunk(
	DKIM *dkim,
	unsigned char *chunkp,
	size_t len
);
Handle a chunk of message input. The input is a buffer of message data which may contain headers or body. An entire message may be fed to the API in one buffer using this function. The API will determine automatically the boundary between header fields and the body of the message and process it accordingly.

Message body content should be in canonical form (e.g., with dot-stuffing removed, if any).

Lines in the data chunk are expected to be CRLF-terminated in the standard way. For input that is not, consider setting the DKIM_LIBFLAGS_FIXCRLF (see dkim_options()), which will cause this function to attempt to auto-detect based on the first line whether the input is CRLF-terminated or not, and adapt accordingly.

dkim_eoh() will be called implicitly by this function upon encountering the end of the message's header block, but the caller must still use dkim_eom() to complete processing of the message. Also, this function should be called with a NULL value for chunkp and/or a zero value for len when no more chunks are to be passed to the API, prior to calling dkim_eom().

DESCRIPTION
Called When dkim_chunk() is called zero or more times between creation of the DKIM handle, using dkim_sign() and dkim_verify(), and dkim_eom().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify()
chunkp Pointer to the start of this block of message data. A value of NULL indicates to the API that no more chunks are to follow.
len The amount of data pointed to by chunkp. A value of 0 indicates to the API that no more chunks are to follow.
RETURN VALUES
  • DKIM_STAT_INVALID indicates the dkim handle was already used in by one of the non-streaming data input calls (e.g. dkim_header(), dkim_eoh() or dkim_body()).
  • DKIM_STAT_INVALID may also indicate that this function was previously called with terminating arguments (see above), implying data input had finished.
  • DKIM_STAT_OK indicates normal completion.
  • May also return other values as passed through from dkim_header(), dkim_eoh() or dkim_body().
NOTES
  • chunkp points to a sequence of bytes. It is not expected to be a C string (a sequence of characters that is terminated by '\0').
  • Dot stuffing and the terminating dot in the message body are expected to be removed by the caller. If they appear within chunkp, they are assumed to be part of the message body and will be included in the hashed data. This is true of any content modification that might be done by the MTA.

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2013, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_close.html000066400000000000000000000041731337314105200247060ustar00rootroot00000000000000 dkim_close()

dkim_close()

[back to index]

SYNOPSIS
#include <dkim.h>
void dkim_close(
	DKIM_LIB *lib
);
Shut down an instantiation of the DKIM service.
DESCRIPTION
Called When dkim_close() is called shutting down the application. It deallocates all allocated resources having to do with the DKIM library.

It does not deallocate resources associated with any existing DKIM handles. Those must be cleaned up first with calls to dkim_free(). Failure to do so will almost certainly cause application failure when those handles are used later, even if only to pass them to dkim_free().

ARGUMENTS
ArgumentDescription
lib The library handle to be shut down, previously returned from a call to dkim_init().
NOTES
  • When this function returns, the data referenced by lib is no longer usable.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_diffheaders.html000066400000000000000000000113761337314105200260500ustar00rootroot00000000000000 dkim_diffheaders()

dkim_diffheaders()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_diffheaders(
	DKIM *dkim,
	dkim_canon_t canon,
	int maxcost,
	char **ohdrs,
	int nohdrs,
	struct dkim_hdrdiff **out,
        int *nout);
);
Attempts to discern how signed header fields were changed in transit in order to debug verification problems.
DESCRIPTION
Called When dkim_diffheaders() can be called at any time after end-of-headers processing (i.e. dkim_eoh()) while verifying.
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_verify().
canon Canonicalization mode that was used to generate the signature from which ohdrs was extracted.
maxcost When comparing two header fields, a "cost" is computed for each difference observed. The library computes the cost of a match by computing the number of character insertions, removals or replacements that would be needed to transition from the first header field to the second; insertions and removals each have a cost of 1 and replacements a cost of 2. Two header fields are considered a match for the purposes of this function if the cost of a comparison is below the value of maxcost. Thus, larger values are more prone to mismatches, but smaller values might not detect serious munging of headers in transit. Insertions and removals are given lower costs because it is presumed most munging in transit changes spaces, but doesn't actually rewrite other content.
ohdrs An array of pointers to NULL-terminated strings containing copies of the original signed headers as extracted from a signature. This can be obtained from signatures that had "z=" tags by using the dkim_ohdrs() function.
nohdrs The number of elements in the ohdrs array.
out A pointer to an array of struct dkim_hdrdiff objects that will be allocated by this function. Each object contains a character pointer called hd_old that refers to the original signed header, and one called hd_new that refers to its corresponding value in the received message.
nout A pointer to an integer that will be updated to contain the number of elements that are placed in the out array.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- the message handle was not initialized for verifying, or a maxcost of 0 was specified
  • DKIM_STAT_INTERNAL -- a regular expression processing error occurred
  • DKIM_STAT_NORESOURCE -- memory exhaustion occurred
  • DKIM_STAT_NOTIMPLEMENT -- the required regular expression library was not available when the library was compiled
NOTES
  • The library must be compiled with an approximate regular expression library in order to provide this service.
  • The returned array of pairs of strings refer to header fields present in both the original header field set and the received header field set that were not the same, but close enough to be considered a match based on the maxcost parameter. This function does not currently detect header fields removed in transit.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_close.html000066400000000000000000000040071337314105200255460ustar00rootroot00000000000000 dkim_dns_close()

dkim_dns_close()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_close(
	DKIM_LIB *libopendkim)
);

Shuts down the DNS resolver in use by the library. This in turn calls either the compiled-in default or the replacement provided by a call to dkim_dns_set_close(). This is automatically called by dkim_close().
DESCRIPTION
Called When dkim_dns_close() can be called at any time.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_config.html000066400000000000000000000044361337314105200257140ustar00rootroot00000000000000 dkim_dns_config()

dkim_dns_config()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_dns_config(
	DKIM_LIB *libopendkim,
        const char * config)
);

Passes arbitrary configuration information to the resolver.
DESCRIPTION
Called When dkim_dns_config() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
config A null-terminated string containing configuration data for the resolver. The string is passed intact to the resolver and is not used by this library.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation (the underlying configuration function returned something other than zero)
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_init.html000066400000000000000000000042661337314105200254130ustar00rootroot00000000000000 dkim_dns_init()

dkim_dns_init()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_init(
	DKIM_LIB *libopendkim)
);

Initializes the DNS resolver to be used by the library. This in turn calls either the compiled-in default or the replacement provided by a call to dkim_dns_set_init(). This is automatically called if the resolver has not yet been initialized and the library needs to perform a DNS lookup.
DESCRIPTION
Called When dkim_dns_init() can be called at any time. It always returns DKIM_DNS_SUCCESS if the resolver was already initialized.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_INVALID -- already initialized
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_nslist.html000066400000000000000000000042301337314105200257530ustar00rootroot00000000000000 dkim_dns_nslist()

dkim_dns_nslist()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_dns_nslist(
	DKIM_LIB *libopendkim,
        const char * nslist)
);

Defines the set of nameservers to be used by the resolver.
DESCRIPTION
Called When dkim_dns_nslist() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
nslist A null-terminated string containing a comma-separated list of nameserver IP addresses to be used.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_close.html000066400000000000000000000056421337314105200264270ustar00rootroot00000000000000 dkim_dns_set_init()

dkim_dns_set_init()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_set_init(
	DKIM_LIB *libopendkim,
        int (*func)(void **)
);

Declares the function to be used by a libopendkim instance when it needs to initialize a DNS resolver. By default, a stub function that initializes the standard system resolver is set.

The function will be passed the following arguments:

  1. A pointer to a handle that will be updated to refer to the instantiated resolver service. The procedure is equivalent to instantiating a resolver service and then passing a pointer representing that service to dkim_dns_set_query_service().
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- query was successfully canceled
  • DKIM_DNS_ERROR -- an error occurred
DESCRIPTION
Called When dkim_dns_set_init() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying. The function will be called implicitly if no service handle has been stored and a query is ready to be started.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to instantiate a DNS resolver.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_config.html000066400000000000000000000061411337314105200265620ustar00rootroot00000000000000 dkim_dns_set_config()

dkim_dns_set_config()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_set_config(
	DKIM_LIB *libopendkim,
        int (*func)(void *, const char *)
);

Declares the function to be used by a libopendkim instance when it needs to pass arbitrary configuration information to an active DNS resolver.

The function will be passed the following arguments:

  1. A pointer to a handle that refers to the instantiated resolver service, via a prior call to to the initialization function defined by dkim_dns_set_init().
  2. A pointer to a NULL-terminated string that includes configuration information to be used by the referenced resolver. The content of string is passed directly to the underlying resolver's configuration function and is not used by this library.
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- query was successfully canceled
  • DKIM_DNS_ERROR -- an error occurred
DESCRIPTION
Called When dkim_dns_set_config() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying. The function will be called implicitly if no service handle has been stored and a query is ready to be started.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to pass configuration information to the current resolver instance.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_init.html000066400000000000000000000057411337314105200262650ustar00rootroot00000000000000 dkim_dns_set_init()

dkim_dns_set_init()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_set_init(
	DKIM_LIB *libopendkim,
        int (*func)(void **)
);

Declares the function to be used by a libopendkim instance when it needs to initialize a DNS resolver. By default, a stub function that initializes the standard system resolver is set.

The function will be passed the following arguments:

  1. A pointer to a handle that will be updated to refer to the instantiated resolver service. The procedure is equivalent to instantiating a resolver service and then passing a pointer representing that service to dkim_dns_set_query_service().
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- the resolver was initialized successfully
  • DKIM_DNS_ERROR -- an error occurred
DESCRIPTION
Called When dkim_dns_set_init() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying. The function will be called implicitly if no service handle has been stored and a query is ready to be started.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to instantiate a DNS resolver. If NULL, no initialization function will be called.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_nslist.html000066400000000000000000000062371337314105200266370ustar00rootroot00000000000000 dkim_dns_set_nslist()

dkim_dns_set_nslist()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_set_nslist(
	DKIM_LIB *libopendkim,
        int (*func)(void *, const char *)
);

Declares the function to be used by a libopendkim instance when it needs to replace the set of nameservers used by a DNS resolver. By default, a stub function that configures the standard system resolver (when supported) is set.

The function will be passed the following arguments:

  1. A pointer to a handle that refers to the instantiated resolver service, via a prior call to to the initialization function defined by dkim_dns_set_init().
  2. A pointer to NULL-terminated, comma-separated list of nameservers to be used. The underlying implementation may not use all of the ones provided as it might have a fixed limit. Consult your resolver's documentation.
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- query was successfully canceled
  • DKIM_DNS_ERROR -- an error occurred
DESCRIPTION
Called When dkim_dns_set_nslist() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying. The function will be called implicitly if no service handle has been stored and a query is ready to be started.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to change the list of nameservers to be queried by the DNS resolver.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_query_cancel.html000066400000000000000000000057071337314105200277760ustar00rootroot00000000000000 dkim_dns_set_query_cancel()

dkim_dns_set_query_cancel()

[back to index]

SYNOPSIS
#include <dkim.h>
void dkim_dns_set_query_cancel(
	DKIM_LIB *libopendkim,
        int (*func)(void *, void *)
);

Declares the function to be used by a libopendkim instance when it needs to cancel a DNS query already in progress. By default, a stub function that does nothing is set, since there is no way to cancel a query in the standard UNIX resolver library.

The function will be passed the following arguments:

  1. An opaque DNS service handle as previously specified by a call to dkim_dns_set_query_service()
  2. A handle for a previously initiated DNS query as returned by the function provided by dkim_dns_set_query_start()
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- query was successfully canceled
  • DKIM_DNS_ERROR -- an error occurred
DESCRIPTION
Called When dkim_dns_set_query_cancel() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to cancel DNS queries.
RETURN VALUES
  • None.
NOTES

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_query_service.html000066400000000000000000000047571337314105200302150ustar00rootroot00000000000000 dkim_dns_set_query_service()

dkim_dns_set_query_service()

[back to index]

SYNOPSIS
#include <dkim.h>
void dkim_dns_set_query_service(
	DKIM_LIB *libopendkim,
        void *service
);

Specifies an opaque handle referring to the DNS service to be used by libopendkim. This handle will be passed to the DNS functions declared using dkim_dns_set_query_start(), dkim_dns_set_query_cancel(), and dkim_dns_set_query_waitreply().
DESCRIPTION
Called When dkim_dns_set_query_service() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
service An opaque handle referring to the DNS service to be used.
RETURN VALUES
  • None.
NOTES

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_query_start.html000066400000000000000000000065711337314105200277060ustar00rootroot00000000000000 dkim_dns_set_query_start()

dkim_dns_set_query_start()

[back to index]

SYNOPSIS
#include <dkim.h>
void dkim_dns_set_query_start(
	DKIM_LIB *libopendkim,
        int (*func)(void *, int, u_char *, u_char *, size_t,
                    void **)
);

Declares the function to be used by a libopendkim instance when it needs to start a DNS query. By default, a stub function that calls the standard UNIX resolver library is set.

The function will be passed the following arguments:

  1. An opaque DNS service handle as previously specified by a call to dkim_dns_set_query_service()
  2. The DNS query type (e.g., ns_t_txt or the older T_TXT)
  3. A NULL-terminated string containing the name to be queried
  4. The address of a buffer into which the result should be written
  5. The length of that buffer
  6. The address of a void * that should be updated to contain an opaque handle for the started query
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- query was successfully initiated
  • DKIM_DNS_ERROR -- an error occurred

The query type should be a DNS resource record type as registered with IANA (here). The constants are typically given names for use in source code via the include file <arpa/nameser.h>.

DESCRIPTION
Called When dkim_dns_set_query_start() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to initiate DNS queries.
RETURN VALUES
  • None.
NOTES

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_query_waitreply.html000066400000000000000000000072531337314105200305670ustar00rootroot00000000000000 dkim_dns_set_query_waitreply()

dkim_dns_set_query_waitreply()

[back to index]

SYNOPSIS
#include <dkim.h>
void dkim_dns_set_query_waitreply(
	DKIM_LIB *libopendkim,
        int (*func)(void *, void *, struct timeval *,
                             size_t *, int *, int *)
);

Declares the function to be used by a libopendkim instance when it needs to wait on a DNS query already in progress. By default, a stub function that merely extracts the reply length nothing is set, since the standard UNIX resolver library is not asynchronous so the answer is already available.

The function will be passed the following arguments:

  1. An opaque DNS service handle as previously specified by a call to dkim_dns_set_query_service()
  2. A handle for a previously initiated DNS query as returned by the function provided by dkim_dns_set_query_start()
  3. A pointer to a structure stipulating a timeout, whose semantics are the same as those for select(2)
  4. A pointer to a size_t that will receive the length of the reply
  5. A pointer to an int that will receive an error code, if any
  6. A pointer to an int that will receive a DKIM_DNSSEC constant describing the security of the reply
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- a reply is available
  • DKIM_DNS_EXPIRED -- the query expired (artifact of libar)
  • DKIM_DNS_ERROR -- an I/O error occurred
  • DKIM_DNS_NOREPLY -- the specified timeout expired before a reply was received
DESCRIPTION
Called When dkim_dns_set_query_waitreply() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to wait on active DNS queries.
RETURN VALUES
  • None.
NOTES

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_set_trustanchor.html000066400000000000000000000061501337314105200276710ustar00rootroot00000000000000 dkim_dns_set_trustanchor()

dkim_dns_set_trustanchor()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_dns_set_trustanchor(
	DKIM_LIB *libopendkim,
        int (*func)(void *, const char *)
);

Declares the function to be used by a libopendkim instance when it needs to pass trust anchor information to an active DNS resolver.

The function will be passed the following arguments:

  1. A pointer to a handle that refers to the instantiated resolver service, via a prior call to to the initialization function defined by dkim_dns_set_init().
  2. A pointer to a NULL-terminated string that includes trust anchor information to be used by the referenced resolver. The content of string is passed directly to the underlying resolver's configuration function and is not used by this library.
The function is expected to return one of the following:
  • DKIM_DNS_SUCCESS -- query was successfully canceled
  • DKIM_DNS_ERROR -- an error occurred
DESCRIPTION
Called When dkim_dns_set_trustanchor() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying. The function will be called implicitly if no service handle has been stored and a query is ready to be started.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function that should be used to pass trust anchor information to the current resolver instance.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dns_trustanchor.html000066400000000000000000000045431337314105200270220ustar00rootroot00000000000000 dkim_dns_trustanchor()

dkim_dns_trustanchor()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_dns_trustanchor(
	DKIM_LIB *libopendkim,
        const char * trustanchor)
);

Passes arbitrary trust anchor configuration information to the resolver.
DESCRIPTION
Called When dkim_dns_trustanchor() can be called at any time, but is presumably most useful prior to doing any DNS operations such as are done during dkim_eoh() when verifying.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
trustanchor A null-terminated string containing trust anchor configuration data for the resolver. The string is passed intact to the resolver and is not used by this library.
RETURN VALUES
  • DKIM_DNS_SUCCESS -- successful operation (the underlying trust anchor configuration function returned something other than zero)
  • DKIM_DNS_ERROR -- an error occurred
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_dnssec.html000066400000000000000000000023131337314105200250520ustar00rootroot00000000000000 DKIM_DNSSEC

DKIM_DNSSEC

[back to index]

DESCRIPTION
Purpose A DKIM_DNSSEC is a mnemonic describing the security of a key record acquired via the DNS.
Possible Values
  • DKIM_DNSSEC_UNKNOWN -- DNSSEC evaluation not done
  • DKIM_DNSSEC_BOGUS -- DNS response failed DNSSEC evaluation
  • DKIM_DNSSEC_INSECURE -- DNS response was not secured by DNSSEC
  • DKIM_DNSSEC_SECURE -- DNS response was secured by DNSSEC

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_eoh.html000066400000000000000000000060741337314105200243560ustar00rootroot00000000000000 dkim_eoh()

dkim_eoh()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_eoh(
	DKIM *dkim
);
Denote end-of-headers for a message.
DESCRIPTION
Called When dkim_eoh() is called when the delimiter between the message's headers and its body is encountered.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify()
NOTES
  • This function may return DKIM_STAT_NOSIG when verifying if no signature was present in the message headers. This is simply advisory; you must continue executing down to the dkim_eom() call to determine whether or not a signature should have been present.
  • This function can return DKIM_STAT_SYNTAX when verifying if a header that must be signed was not included in a received signature, or if the message appeared to contain no sender header field. In the latter case, the dkim handle is rendered unusable by future calls to dkim_body() or dkim_eom().
  • This function can return DKIM_STAT_CANTVRFY when verifying if all discovered signatures were either marked to be ignored, contained syntax errors, or failed verification attempts. This is only tested if the DKIM_LIBFLAG_EOHCHECK library flag is set.
  • This function can return DKIM_STAT_SYNTAX in either mode if the input message does not conform to the header field count checks imposed by the DKIM_LIBFLAG_STRICTHDRS library flag.
  • This function can return DKIM_STAT_NORESOURCE for a verifying handle if an attempt to construct a DNS query based on the selector and domain in a signature exceeded the maximum allowable query size.

Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_eom.html000066400000000000000000000076671337314105200243740ustar00rootroot00000000000000 dkim_eom()

dkim_eom()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_eom(
	DKIM *dkim,
	bool *testkey
);
Denote end-of-message for a message. When verifying, process signatures in order; when signing, compute all signatures.
DESCRIPTION
Called When dkim_eom() is called after the entire body of the message has been passed to the API via zero or more calls to dkim_body().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify()
testkey Optional pointer to a boolean value which is updated to indicate whether the key found (if any) is marked as being a test key.
RETURN VALUES
  • DKIM_STAT_INVALID may indicate the dkim handle was rendered unusable by a previous call, likely to dkim_eoh(), or simply that dkim_eoh() has not yet been called for this handle.
  • DKIM_STAT_INVALID may also indicate the dkim handle was passed to dkim_chunk() for message chunk processing but the end of message was never signaled via that interface.
  • DKIM_STAT_INVALID returned when signing may indicate that the key provided for signing did not meet the minimum key size requirement (see dkim_options()).
  • DKIM_STAT_CANTVRFY is returned when passed a signing handle bound via dkim_resign() to a verifying handle if the latter yielded no valid signatures.
  • Other possible return values include all the DKIM_STAT values.
NOTES
  • By default, when verifying, this function processes all signatures, in order. If the DKIM_LIBFLAGS_VERIFYONE flag is set on the library, then processing will stop after one good signature is found. There may be other signatures before or after that one in the message whose evaluation might be meaningful to the calling application. In that case, the calling application should use the final handling callback (see dkim_set_final() to get an opportunity to process all of the signatures and possibly reorder them as per the application's preference. With the above flag set, this function will use the signatures as reordered by that function (or in arrival order if no reordering is done) and act on the first valid one, or the first one if none are valid.

Copyright (c) 2005, 2007, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2013, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_flush_cache.html000066400000000000000000000043531337314105200260450ustar00rootroot00000000000000 dkim_flush_cache()

dkim_flush_cache()

[back to index]

SYNOPSIS
#include <dkim.h>

int dkim_flush_cache(DKIM_LIB *lib);
Flush cached entries when caching is enabled in the library.
DESCRIPTION
Called When dkim_flush_cache() can be called at any time.
ARGUMENTS
ArgumentDescription
lib The DKIM library instance whose cache should be flushed, previously created by a call to dkim_init().
RETURN VALUES
ValueDescription
-1 Caching is not active for this library instance.
>= 0 Number of records flushed.
NOTES
  • Caching is selected by setting the DKIM_LIBFLAGS_CACHE flag using the dkim_options() function.
  • Caching requires a special compile-time option since it also adds a library dependency to applications.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_free.html000066400000000000000000000041721337314105200245210ustar00rootroot00000000000000 dkim_free()

dkim_free()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_free(
	DKIM *dkim
);
Release resources associated with a signing or verifying handle.
DESCRIPTION
Called When dkim_free() must be passed a handle returned by dkim_sign() or dkim_verify()
Effects Releases resources that were allocated and assigned to the handle dkim when it was returned by dkim_sign() or dkim_verify(). The handle dkim may not be reused.
ARGUMENTS
ArgumentDescription
dkim A DKIM handle returned by a previous call to dkim_sign() or dkim_verify().
RETURN VALUES
  • DKIM_STAT_OK -- operation was successful
NOTES None.

Copyright (c) 2005, 2006 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_get_msgdate.html000066400000000000000000000045501337314105200260630ustar00rootroot00000000000000 dkim_get_msgdate()

dkim_get_msgdate()

[back to index]

SYNOPSIS
#include <dkim.h>

uint64_t dkim_get_msgdate(
	DKIM *dkim
);
Retrieve the value of a message's Date: header field.
DESCRIPTION
Called When dkim_get_msgdate() can be called at any time after end-of-headers has been reached (i.e. dkim_eoh() has been called).
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
0 A Date: header field was not found, or one was found but could not be parsed, or the feature was not enabled when the DKIM library was compiled.
otherwise A UNIX time_t translation of the value of the Date: header field, returned as a 64-bit quantity.
NOTES
  • Presumes the provided Date: header field is in standard format.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_get_reputation.html000066400000000000000000000060441337314105200266310ustar00rootroot00000000000000 dkim_get_reputation()

dkim_get_reputation()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_get_reputation(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
	char *qroot,
	int *rep
);
Query an experimental DKIM reputation service.
DESCRIPTION
Called When dkim_get_reputation() can be called at any time after the signature information handles are initialized in the call to dkim_eoh().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle.
sig Signature-specific handle.
qroot The root of the reputation query. This is a location in the DNS at which the published reputation data are rooted.
rep A pointer to an integer that will be updated to contain the reputation reported about the message's signer.
RETURN VALUES
ValueDescription
DKIM_STAT_OK A reputation was retrieved.
DKIM_STAT_NOKEY No reputation data was available for this signer.
DKIM_STAT_CANTVRFY An error occurred retrieving the reputation data.
DKIM_STAT_INTERNAL An internal error occurred.
DKIM_STAT_NOTIMPLEMENT The required code supporting this feature was not enabled when the library was built.
NOTES

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_get_signer.html000066400000000000000000000036761337314105200257360ustar00rootroot00000000000000 dkim_get_signer()

dkim_get_signer()

[back to index]

SYNOPSIS
#include <dkim.h>
const unsigned char *dkim_get_signer(
	DKIM *dkim);
);
Returns the current signer (i.e. value to be used in the "i=" tag) for a signing handle.
DESCRIPTION
Called When dkim_get_signer() can be called at any time prior to signature generation.
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign().
RETURN VALUES
  • NULL -- no signer has been requested, meaning no "i=" tag will be included in the generated signature
  • otherwise -- a pointer to a terminated string containing the signer address previously requested
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_get_sigsubstring.html000066400000000000000000000062741337314105200271670ustar00rootroot00000000000000 dkim_get_sigsubstring()

dkim_get_sigsubstring()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_get_sigsubstring(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
        char *buf,
        size_t *buflen
);
Retrieve a minimal substring of the actual signature (i.e. the "b=" tag value) from a specified signature, of sufficient length to identify this signature uniquely from others.
DESCRIPTION
Called When dkim_getsig() is called after dkim_eom() when dkim is a verifying handle, i.e. one returned by an earlier call to dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign().
sig Signature-specific handle, retrieved by a prior call to dkim_getsiglist().
buf Pointer to a buffer that should receive a minimal unique substring of the digital signature portion of sig.
buflen The address of an integer that should contain the number of bytes available at buf and will be updated to contain the number of bytes needed to produce a minimal substring.
NOTES
  • No fewer than eight bytes will be requested. If two or more signatures have the same initial byte sequences in "b=" tags, larger lengths will be required, theoretically requiring as much as the entire signature.
  • If the size of buf is too small to contain the minimal substring of sig, DKIM_STAT_NORESOURCE is returned, buflen will be updated to indicate the minimal number of bytes required, and buf will be unchanged.
  • The string written to buf will be NULL-terminated unless the provided buffer is exactly the right size to contain the output.

Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_get_user_context.html000066400000000000000000000041201337314105200271520ustar00rootroot00000000000000 dkim_get_user_context()

dkim_get_user_context()

[back to index]

SYNOPSIS
#include <dkim.h>
	void * dkim_get_user_context(
	DKIM *dkim
);
Retrieves an opaque user context pointer previously associated with a DKIM handle by a call to dkim_set_user_context(), if any.
DESCRIPTION
Called When dkim_get_user_context() can be called at any time.
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES The user-specific context pointer previously associated with the named handle via a call to dkim_set_user_context(), if any. If none has been set, the value NULL will be returned.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions get forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getcachestats.html000066400000000000000000000070451337314105200264240ustar00rootroot00000000000000 dkim_getcachestats()

dkim_getcachestats()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_getcachestats(
                        DKIM_LIB *lib,
			u_int *queries,
			u_int *hits,
			u_int *expired,
			u_int *keys,
			_Bool reset
);
Retrieve libopendkim caching statistics.
DESCRIPTION
Called When dkim_getcachestats() can be called at any time.
ARGUMENTS
ArgumentDescription
lib A DKIM library handle as previously returned by a call to dkim_init().
queries Pointer to an unsigned integer which will receive the number of queries libopendkim has processed. This can be NULL if that datum is not of interest to the caller.
hits Pointer to an unsigned integer which will receive the number of queries which were found in the cache being maintained by the library. This can be NULL if that datum is not of interest to the caller.
expired Pointer to an unsigned integer which will receive the number of queries which were found in the cache but whose time-to-live value had expired and thus a re-query was required. This can be NULL if that datum is not of interest to the caller.
keys Pointer to an unsigned integer which will receive the number of records present in the cache. Note that this includes records that have passed their time-to-live limits but have not yet been purged. This can be NULL if that datum is not of interest to the caller.
reset If TRUE, the queries, hits and expired counters will be reset to 0. No change is made to cached data.
RETURN VALUES
  • DKIM_STAT_OK -- requested values returned
  • DKIM_STAT_INVALID -- the cache has not yet been initialized
  • DKIM_STAT_NOTIMPLEMENT -- library was not compiled with caching enabled
NOTES
  • Caching is enabled via the setting of the DKIM_LIBFLAGS_CACHE library option using the dkim_options() function.
  • Caching must be enabled in the library at compile time since it establishes an extra library dependency.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, 2013, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getdomain.html000066400000000000000000000050431337314105200255450ustar00rootroot00000000000000 dkim_getdomain()

dkim_getdomain()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_getdomain(
	DKIM *dkim
);
Retrieve the sending domain associated with a message.
DESCRIPTION
Called When dkim_getdomain() can be called at any time after a handle is initialized with a call to dkim_sign() or dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
NULL The sending domain has not or could not be determined from the message represented by this handle.
otherwise A pointer to the sending domain.
NOTES
  • This domain is selected by finding the first "From" header field Note that it is not guaranteed that this field was included in the set of fields fed to the DKIM signature hashes (assuming it was signed), and in any case its value may or may not have been valid at the time the message was generated.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_geterror.html000066400000000000000000000042751337314105200254350ustar00rootroot00000000000000 dkim_geterror()

dkim_geterror()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_geterror(
	DKIM *dkim
);
Retrieve the last stored error message associated with a DKIM handle.
DESCRIPTION
Called When dkim_geterror() can be called at any time after a handle is initialized with a call to dkim_sign() or dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
NULL No error message has been stored for this handle.
otherwise A pointer to the last stored error string.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getid.html000066400000000000000000000042771337314105200247020ustar00rootroot00000000000000 dkim_getid()

dkim_getid()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_getid(
	DKIM *dkim
);
Retrieve the "id" parameter from a DKIM handle.
DESCRIPTION
Called When dkim_getid() can be called at any time after a handle is initialized with a call to dkim_sign() or dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
NULL The handle was not initialized with a valid id parameter.
otherwise The same id pointer with which the handle was initialized.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getmode.html000066400000000000000000000042501337314105200252210ustar00rootroot00000000000000 dkim_getmode()

dkim_getmode()

[back to index]

SYNOPSIS
#include <dkim.h>

int dkim_getmode(
	DKIM *dkim
);
Retrieve the mode of a DKIM handle.
DESCRIPTION
Called When dkim_getmode() can be called at any time after a handle is initialized with a call to dkim_sign() or dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
DKIM_MODE_SIGN The DKIM handle provided is a signing handle.
DKIM_MODE_VERIFY The DKIM handle provided is a verifying handle.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getpartial.html000066400000000000000000000050001337314105200257230ustar00rootroot00000000000000 dkim_getpartial()

dkim_getpartial()

[back to index]

SYNOPSIS
#include <dkim.h>

_Bool dkim_getpartial(
	DKIM *dkim
);
DESCRIPTION
Called When dkim_getpartial() can be called at any time after a DKIM handle has been initialized by either dkim_sign() or dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
TRUE The message-specific handle has been flagged to produce a signature with an "l=" tag by a previous call to dkim_setpartial().
FALSE The message-specific handle has been flagged to produce a signature with an "l=" tag.
NOTES
  • Regardless if the setting of this bit inside a message-specific handle, a signature with "l=" will be generated if the DKIM_LIBFLAGS_SIGNLEN flag was set on the library handle.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getresultstr.html000066400000000000000000000040621337314105200263450ustar00rootroot00000000000000 dkim_getresultstr()

dkim_getresultstr()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_getresultstr(
	DKIM_STAT result
);
Retrieve a text conversion for a DKIM_STAT result code.
DESCRIPTION
Called When dkim_getresultstr() can be called at any time after a function that returns a DKIM_STAT result code.
ARGUMENTS
ArgumentDescription
result A DKIM_STAT result code to be translated.
RETURN VALUES
ValueDescription
NULL The value of result was not recognized.
otherwise A pointer to a NULL-terminated string containing a text translation of result.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getsighdr.html000066400000000000000000000057741337314105200255710ustar00rootroot00000000000000 dkim_getsighdr()

dkim_getsighdr()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_getsighdr(
	DKIM *dkim,
        unsigned char *buf,
        size_t len,
        size_t initial
);
Compute and retrieve the signature header for a message.
DESCRIPTION
Called When dkim_getsig() is called after dkim_eom() when dkim is a signing handle, i.e. one returned by an earlier call to dkim_sign().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign().
buf A buffer into which the signature header should be stored.
len Number of bytes available at buf.
initial Line length already consumed on the first line. Used to leave space when wrapping headers for the name of the header itself.
NOTES
  • It is an error to call this function with a handle that was created using dkim_verify().
  • If for example, you want to have your headers wrapped at 75 bytes and the header to be added will be called "DKIM-Signature", the initial value should be 16 (length of the header's name plus room for a colon and a space). The default margin is 75; see dkim_set_margin().
  • When signing and "simple" canonicalization is in use, the header added to the message must be identical to the internal version used to generate the signature, or the message will not verify. In that case, the value of initial should be 16 (or more portably, strlen(DKIM_SIGNHEADER) + 2).

Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getsighdr_d.html000066400000000000000000000071321337314105200260620ustar00rootroot00000000000000 dkim_getsighdr_d()

dkim_getsighdr_d()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_getsighdr_d(
	DKIM *dkim,
        size_t initial,
        unsigned char **buf,
        size_t *len
);
Compute and retrieve the signature header for a message. This is similar to dkim_getsighdr() except that memory will be allocated for an arbitrarily long signature header, and a pointer to that memory will be returned as well as the length of the string at that location.

The memory thus allocated will be deallocated by the library when the dkim handle is closed.

DESCRIPTION
Called When dkim_getsig() is called after dkim_eom() when dkim is a signing handle, i.e. one returned by an earlier call to dkim_sign().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign().
initial Line length already consumed on the first line. Used to leave space when wrapping headers for the name of the header itself.
buf The address of a pointer that will be updated to reference a buffer into which the generated signature header was placed. The buffer is NUL-terminated.
len The address of an integer that will be updated to contain the length of the generated signature header. The length does not include the NUL byte at the end.
NOTES
  • It is an error to call this function with a handle that was created using dkim_verify().
  • If for example, you want to have your headers wrapped at 75 bytes and the header to be added will be called "DKIM-Signature", the initial value should be 16 (length of the header's name plus room for a colon and a space). The default margin is 75; see dkim_set_margin().
  • When signing and "simple" canonicalization is in use, the header added to the message must be identical to the internal version used to generate the signature, or the message will not verify. In that case, the value of initial should be 16 (or more portably, strlen(DKIM_SIGNHEADER) + 2).

Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getsiglist.html000066400000000000000000000062621337314105200257600ustar00rootroot00000000000000 dkim_getsiglist()

dkim_getsiglist()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_getsiglist(
	DKIM *dkim,
	DKIM_SIGINFO ***sigs,
	int *nsigs
);
Retrieve the array of DKIM_SIGINFO handles associated with a message.
DESCRIPTION
Called When dkim_getsiglist() can be called at any time after dkim_eoh() has been called.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign or dkim_verify.
sigs A pointer to an array of DKIM_SIGINFO handles representing all of the signatures present on the message being handled (updated).
nsigs A pointer to an integer which will be updated to contain the number of signatures on the message being handled (and thus, the size of the array referenced by sigs).
RETURN VALUES
ValueDescription
DKIM_STAT_INVALID No siglist message has been stored for this handle. This usually means dkim_eoh() has not yet been called.
DKIM_STAT_OK The pointer to the signature array and the count have been returned in the provided locations.
NOTES
  • The array returned is allocated and maintained by the library, and must not be deallocated by the caller.
  • Initially, the array's order mirrors the order of signature fields found in the message being verified. The caller is free to rearrange this order. This same array is passed to all of the callbacks, so reordering done in one will be visible to the others.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getsignature.html000066400000000000000000000047521337314105200263050ustar00rootroot00000000000000 dkim_getsignature()

dkim_getsignature()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_SIGINFO *dkim_getsignature(
	DKIM *dkim
);
Retrieve the signature ultimately used to verify a message.
DESCRIPTION
Called When dkim_getsignature() is called after dkim_eom() to get a handle referring to the signature which will be used to yield a final result to the caller.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_verify.
RETURN VALUES
ValueDescription
NULL
  • The function was called before dkim_eom.
  • The function was called with a handle that was not opened for verification.
  • The message represented by dkim was not signed.
otherwise A handle referring to the first signature found to be valid that was not flagged to be ignored by the caller, or if none were valid, the first signature not flagged to be ignored by the caller.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getsslbuf.html000066400000000000000000000041371337314105200255770ustar00rootroot00000000000000 dkim_getsslbuf()

dkim_getsslbuf()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_getsslbuf(
	DKIM *dkim
);
Retrieve from a DKIM handle the SSL error buffer, which will contain the SSL-specific error string, if any.
DESCRIPTION
Called When dkim_getsslbuf() can be called at any time after the cryptographic phase of signature processing has occurred, i.e., after dkim_eoh().
ARGUMENTS
ArgumentDescription
dkim DKIM signing handle.
RETURN VALUES
ValueDescription
NULL No error message was recorded.
otherwise A pointer to the SSL error message recorded for the provided signing handle.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_getuser.html000066400000000000000000000050251337314105200252540ustar00rootroot00000000000000 dkim_getuser()

dkim_getuser()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_getuser(
	DKIM *dkim
);
Retrieve the sending user associated with a message.
DESCRIPTION
Called When dkim_getuser() can be called at any time after a handle is initialized with a call to dkim_sign() or dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
NULL The sending user has not or could not be determined from the message represented by this handle.
otherwise A pointer to the sending user.
NOTES
  • This user is selected by finding the first "From" header field. Note that it is not guaranteed that this field was included in the set of fields fed to the DKIM signature hashes (assuming it was signed), and in any case its value may or may not have been valid at the time the message was generated.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_header.html000066400000000000000000000045511337314105200250310ustar00rootroot00000000000000 dkim_header()

dkim_header()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_header(
	DKIM *dkim,
	char *header,
	size_t len)
);
Handle a message header field.
DESCRIPTION
Called When dkim_header() is called zero or more times between dkim_sign() or dkim_verify() and dkim_eoh(), once per message header field.
ARGUMENTS
ArgumentDescription
dkim Per-message DKIM handle.
header The header field being input, including its name, value and separating colon (":") character.
len Number of bytes to read from header.
NOTES
  • The value of header should not contain a trailing CRLF as this will be added by the canonicalization code. However, a CRLF may appear elsewhere in the value if, for example, the header field is meant to be wrapped.
  • A header field whose name includes a semi-colon cannot be used as it will produce a syntactically invalid signature. Such header fields cause this function to return DKIM_STAT_SYNTAX.

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_init.html000066400000000000000000000061201337314105200245360ustar00rootroot00000000000000 dkim_init()

dkim_init()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_LIB *dkim_init(
	void *(*mallocf)(void *closure, size_t nbytes),
	void (*freef)(void *closure, void *p)
);
Create a new instantiation of the DKIM service, for signing or verifying Internet messages.
DESCRIPTION
Called When dkim_init() is called when setting up the application. The handle it returns is used when generating per-message handles for signing and verifying, and is used to declare optional alternate memory allocate and free functions.
ARGUMENTS
ArgumentDescription
mallocf Optional alternate memory allocation function. It must take two parameters: a void pointer which is the memory closure specified in calls to dkim_sign() or dkim_verify(), and the number of bytes to be allocated. This allows memory allocations for a specific message to be made within the same closure.
freef Optional alternate memory release function. It must take two parameters: a void pointer which is the memory closure specified in calls to dkim_sign() or dkim_verify(), and the pointer to memory to be released. This allows memory allocations for a specific message to be made within the same closure.
NOTES
RETURN VALUES
  • On success, a pointer to the created DKIM_LIB handle is returned.
  • On failure, NULL is returned. Generally this means a memory allocation failure.

Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_key_syntax.html000066400000000000000000000043711337314105200257770ustar00rootroot00000000000000 dkim_key_syntax()

dkim_key_syntax()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_key_syntax(
	DKIM *dkim,
	unsigned char *str,
	size_t len
);
Validates the syntax of a key record, returning a result. The signature is not stored or used, only validated.

DESCRIPTION
Called When dkim_key_syntax() can be called at any time.
ARGUMENTS
ArgumentDescription
dkim DKIM handle, returned by a prior call to dkim_sign() or dkim_verify().
str Pointer to a buffer containing the key record to be evaluated.
len Number of bytes available at str.
RETURN VALUES
Return ValueDescription
DKIM_STAT_OK The key record appeared to be syntactically valid.
DKIM_STAT_SYNTAX The key record did not appear to be syntactically valid.

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_lib.html000066400000000000000000000024011337314105200243370ustar00rootroot00000000000000 DKIM_LIB

DKIM_LIB

[back to index]

DESCRIPTION
Purpose A DKIM_LIB handle is returned by a successful call to dkim_init() and contains context information needed for a single instance of the libopendkim service to be used. It can be used by several threads at once.
NOTES

Copyright (c) 2005 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_libfeature.html000066400000000000000000000065061337314105200257250ustar00rootroot00000000000000 dkim_libfeature()

dkim_libfeature()

[back to index]

SYNOPSIS
#include <dkim.h>

_Bool dkim_libfeature(
	DKIM_LIB *lib,
        u_int fc
);
Tests for availability of a specific feature in the library.
DESCRIPTION
Called When dkim_libfeature() can be called at any time after acquiring a library handle from dkim_init().
ARGUMENTS
ArgumentDescription
dkim Library instance handle, returned by dkim_init.
fc A code representing a specific feature of the library. Possible values:
Feature NameDescription
DKIM_FEATURE_DIFFHEADERS Underlying code required to provide the dkim_diffheaders() facility.
DKIM_FEATURE_PARSE_TIME Underlying code required to provide the dkim_get_msgdate() facility.
DKIM_FEATURE_QUERY_CACHE Underlying code required to do local caching of DNS replies (i.e., key records).
DKIM_FEATURE_SHA256 Underlying code required to do SHA256 hashing when signing or verifying.
DKIM_FEATURE_DNSSEC Underlying code required to conduct DNSSEC evaluation of replies.
DKIM_FEATURE_OVERSIGN Capability to "over-sign" header fields to prevent later addition of signed fields.
NOTES
  • None.

Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2013, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_libversion.html000066400000000000000000000027251337314105200257560ustar00rootroot00000000000000 dkim_libversion()

dkim_libversion()

[back to index]

SYNOPSIS
#include <dkim.h>

uint32_t dkim_libversion(void);

Returns the version of the library against which an application was linked. The version is encoded as a four-octet integer, with the octets representing (from highest-order to lowest-order) the release number, the major version number, the minor version number, and the patch level.
DESCRIPTION
Called When dkim_libversion() can be called at any time.
ARGUMENTS None.
NOTES
  • None.

Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_mail_parse.html000066400000000000000000000042201337314105200257060ustar00rootroot00000000000000 dkim_mail_parse()

dkim_mail_parse()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_mail_parse(
	char *line,
	char **user_out,
	char **domain_out
);
Parse an RFC2822 header for a user and hostname.
DESCRIPTION
Called When At any time.
ARGUMENTS
ArgumentDescription
line Input line, not including the name of the header.
user_out Pointer to a variable of type (char *) which will be set to point to the "local-part" (user ID) found in the input.
domain_out Pointer to a variable of type (char *) which will be set to point to the domain found in the input.
RETURN VALUE 0 on success, other on failure. The failure codes are internal to the library for now.
NOTES
  • line is modified.
  • This function is not part of the DKIM specification. It is provided as a facility to implementors to reduce code duplication.

Copyright (c) 2004, 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_mail_parse_multi.html000066400000000000000000000050601337314105200271230ustar00rootroot00000000000000 dkim_mail_parse()

dkim_mail_parse()

[back to index]

SYNOPSIS
#include <dkim.h>
int dkim_mail_parse_multi(
	char *line,
	char **users_out,
	char **domains_out
);
Parse an RFC2822 header for a set of users and hostnames. Intended for use on header fields that might contain multiple addresses, such as To: and Cc:.
DESCRIPTION
Called When At any time.
ARGUMENTS
ArgumentDescription
line Input line, not including the name of the header.
users_out Pointer to a variable of type (unsigned char **) that will be set to point to an array of "local-part"s (user ID) found in the input.
domains_out Pointer to a variable of type (unsigned char **) which will be set to point to an array of domains found in the input.
RETURN VALUE 0 on success, other on failure. The failure codes are internal to the library for now.
NOTES
  • line is modified.
  • The arrays returned will be of the same size and entries are correspondent, so the first element from each refer to the first address found, etc.
  • The caller is responsible for deallocating the returned arrays once they are no longer needed.
  • This function is not part of the DKIM specification. It is provided as a facility to implementors to reduce code duplication.

Copyright (c) 2004, 2005, 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_minbody.html000066400000000000000000000046751337314105200252510ustar00rootroot00000000000000 dkim_minbody()

dkim_minbody()

[back to index]

SYNOPSIS
#include <dkim.h>

unsigned long dkim_minbody(
	DKIM *dkim
);
Retrieve the number of bytes of message body still required to satisfy all canonicalizations.
DESCRIPTION
Called When dkim_minbody() can be called at any time after dkim_eoh() has been called.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify().
RETURN VALUES
ValueDescription
0 All canonicalizations referenced by the message-specific handle have enough data to compute final hashes; no additional body data are required.
ULONG_MAX At least one canonicalization referenced by the message-specific handle wants the entire message body.
otherwise The number of bytes required to satisfy all canonicalizations referenced by the message-specific handle.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_ohdrs.html000066400000000000000000000066461337314105200247270ustar00rootroot00000000000000 dkim_ohdrs()

dkim_ohdrs()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_ohdrs(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
        unsigned char **ptrs, int *pcnt)
);
Retrieve the original header set from the "z=" tag in a received signature if present.
DESCRIPTION
Called When dkim_ohdrs() is called after dkim_eom() to get the original header set included in a signature on a message, if present, for diagnostic purposes. The original headers can be compared to the received headers to detect modifications in transit which prevented successful verification of the message.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_verify.
sig Signature handle from which the original headers should be extracted.
ptrs A pointer to a an array of (char *) pointers which will be updated to point to the original headers.
pcnt On input, this is used as the count of available pointers in the ptrs array. When returned, this value indicates the number of headers available. If it is higher on return than it was when called, then there were more headers than there were pointers provided.
RETURN VALUES
ValueDescription
DKIM_STAT_INVALID The function was called before dkim_eom, or with a handle that was not opened for verification.
DKIM_STAT_INVALID The value contained in the "z=" tag contained corruption.
DKIM_STAT_NORESOURCE A memory allocation operation failed.
DKIM_STAT_OK Successful completion.
NOTES
  • If there was no "z=" tag present, the value referenced by pcnt will be set to zero.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_options.html000066400000000000000000000371741337314105200253030ustar00rootroot00000000000000 dkim_options()

dkim_options()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_options(
	DKIM_LIB *lib,
        int op,
        int opt,
        void *data,
        size_t len
);
Sets or retrieves options to alter the behaviour of certain aspects of the library's operation.
DESCRIPTION
Called When dkim_options() can be called at any time after acquiring a library handle from dkim_init().
ARGUMENTS
ArgumentDescription
dkim Library instance handle, returned by dkim_init.
op Either DKIM_OP_SETOPT to set a current library option, or DKIM_OP_GETOPT to retrieve a current library option.
opt One of the following macros, to indicate which library option should be retrieved or changed. Possible values:
Option NameDescription
DKIM_OPTS_CLOCKDRIFT data refers to a uint64_t that contains the number of seconds of clock drift that should be tolerated when determining whether or not a signature either has expired or was generated in the future. The default is 300 seconds (five minutes).
DKIM_OPTS_FIXEDTIME data refers to a uint64_t that contains a fixed time specification to use during signature generation. This follows the same form as a time_t but allows for larger integers.
DKIM_OPTS_FLAGS data refers to an unsigned integer which contains a bitwise-OR of desired flags. See below for the list of known flags.
DKIM_OPTS_MINKEYBITS data refers to a u_int that contains the minimum number of bits that are to be conisdered acceptable. The default is 1024.
DKIM_OPTS_MUSTBESIGNED data refers to an ordered, NULL-terminated array of header names which, when verifying a message, must be covered by a signature for the signature to be considered valid. The default is to make no such assertion. If data refers to a NULL pointer, the default is restored.
DKIM_OPTS_OVERSIGNHDRS data refers to an unordered, NULL-terminated array of pointers to NULL-terminated strings that name header fields which should be included in the header lists ("h=" tags) of signatures once more than the number of occurrences that were signed. This prevents later handlers from adding instances of those header fields without invalidating the signature. This list is empty by default.
DKIM_OPTS_QUERYINFO data refers to a string in which query information is stored. See dkim_query_t for more information.
DKIM_OPTS_QUERYMETHOD data refers to a dkim_query_t containing a value which should override any q= value in signatures during verifications.
DKIM_OPTS_REQUIREDHDRS data refers to an ordered, NULL-terminated array of header field names that should be considered mandatory when determining the validity of an input message for signing. The default is to require a From field only. The caller's list completely replaces this list. If data refers to a NULL pointer, the default is restored.
DKIM_OPTS_SIGNATURETTL data refers to a uint64_t that contains the time-to-live, in seconds, of signatures to be applied during signature generation.
DKIM_OPTS_SIGNHDRS data refers to an unordered, NULL-terminated array of header field names. Input header fields whose names match an entry in this list will be signed. Wildcarding using the asterisk ("*") character, meaning "match zero or more characters", is permitted. The From header field is mandatory and thus implicitly added to any list provided by the caller. The constant dkim_should_signhdrs may be specified as the data, which contains all of the header fields RFC6376 Section 5.4 says should be signed. The default is to sign all header fields. If data refers to a NULL pointer, the default is restored. Attempting DKIM_OP_GETOPT on this option returns an error as it is converted internally to regular expressions and not currently stored in a useable form.
DKIM_OPTS_SKIPHDRS data refers to an unordered, NULL-terminated array of header names which are the ones that should be skipped when processing a message for signing. The default is to skip no headers. The constant dkim_should_not_signhdrs may be specified as the data, which contains all of the headers RFC6376 Section 5.4 says should not be signed. Wildcarding using the asterisk ("*") character, meaning "match zero or more characters", is permitted. If data refers to a NULL pointer, the default is restored. Attempting DKIM_OP_GETOPT on this option returns an error as it is converted to regular expressions and not currently stored in a useable form.
DKIM_OPTS_TMPDIR data refers to a string which is the directory libopendkim should use for creating temporary files.
DKIM_OPTS_TIMEOUT data refers to an unsigned integer indicating the timeout, in seconds, to be used when doing DNS queries to retrieve key records.
data If the operation is DKIM_OP_GETOPT, this specifies the address to which to write the retrieved value. If the operation is DKIM_OP_SETOPT, this specifies the address from which to copy the new option value.
len Number of bytes available for reading/writing at data. Usually one can simply use sizeof(data) here.
FLAGS When setting or retreiving library flags, the method is to specify a bitwise-OR of flag bits in an unsigned integer. The recognized flags are:
DKIM_LIBFLAGS_ACCEPTDK Allow references to key records formatted for DomainKeys (RFC4870). This means a key record retrieved from DNS that has no "v=" tag will be treated slightly differently; specifically, an empty "g=" tag in the key matches all senders (the DomainKeys way) rather than no senders (the DKIM way). This flag has no other effect.
DKIM_LIBFLAGS_ACCEPTV05 Accept signatures with version strings of "0.5", i.e. those which were based on some draft versions of the DKIM specification. Note that this does not change or relax the rules applied by this implementation, and thus these older signatures still may not verify due to evolutions of the specification that took place during the use of that version string.
DKIM_LIBFLAGS_BADSIGHANDLES Create DKIM_SIGINFO handles even for signatures that had syntax errors. This also means dkim_chunk() will not return a syntax error code when it encounters a DKIM signature with a syntax error in it.
DKIM_LIBFLAGS_CACHE Maintain a local cache of retrieved key records, rather than relying on the DNS servers to do so. May improve performance if, for example, the DNS server is not local. Requires that libopendkim be compiled with the QUERY_CACHE option since doing so adds a library dependency to the build.
DKIM_LIBFLAGS_DELAYSIGPROC Normally the key retrieval and public key validation takes place in the dkim_eoh() function, and the body hash verification takes place in dkim_eom() function. Setting this flag delays all processing of signatures until dkim_eom(). This means the caller will be unable to evaluate signature validity on completion of dkim_eoh() and will have to wait until after dkim_eom() (or the final processing callback if such is defined).
DKIM_LIBFLAGS_DROPSIGNER If a caller attempts to generate a signature for which a specific signer address is requested and the domain of the signer is not the same as or a subdomain of the signing domain, the default behaviour is to return an error from dkim_gensighdr() since a signature thus generated would violate the DKIM specification. If this flag is set, the signature will still be generated but the "i=" tag will be omitted so the signature is still compliant.
DKIM_LIBFLAGS_EOHCHECK Perform a signature check at the end of dkim_eoh(). This will cause dkim_eoh() to return an error code if no useable signatures were found in the message.
DKIM_LIBFLAGS_FIXCRLF Convert "naked" CR and LF characters into CRLFs when canonicalizing.
DKIM_LIBFLAGS_KEEPFILES Keep temporary files for manual debugging purposes. (Also requires that DKIM_LIBFLAGS_TMPFILES be set.)
DKIM_LIBFLAGS_REPORTBADADSP When doing the ADSP query, a response that is a syntax error will by default be ignored. Setting this flag causes an error to be returned. This can be common when, for example, wildcard TXT records are used to publish other data.
DKIM_LIBFLAGS_REQUESTREPORTS Includes an "r=y" tag in generated signatures, requesting participating verifiers send back forensic information about the verified message when validation fails. Useful for debugging signature validation issues.
DKIM_LIBFLAGS_SIGNLEN When signing messages, include in the signature the number of bytes that were canonicalized even when a length limit wasn't specified by the caller.
DKIM_LIBFLAGS_STRICTHDRS Refuse to sign or verify a message that doesn't conform to the header field count rules specified in RFC5322 Section 3.6, and have a properly formed From field. Other checks may also be enforced in the future.
DKIM_LIBFLAGS_STRICTRESIGN Refuse to generate a signature from a signing handle bound to a verifying handle (see dkim_resign()) if the verifying handle yielded no valid signatures.
DKIM_LIBFLAGS_TMPFILES Make temporary files for debugging purposes. See dkim_sig_reportinfo() for an example of how this might be useful.
DKIM_LIBFLAGS_VERIFYONE When verifying, only process signatures until the first good one is found (by default, all of them will be attempted).
DKIM_LIBFLAGS_ZTAGS Include the original header set encoded into a "z=" tag in the signature for diagnostic use by the receiver.
NOTES
  • None.

Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_param_t.html000066400000000000000000000035631337314105200252260ustar00rootroot00000000000000 dkim_param_t

dkim_param_t

[back to index]

DESCRIPTION
Purpose A dkim_param_t is a value from an enumerated list of the possible signature parameters (tags) available.
Possible Values
  • DKIM_PARAM_UNKNOWN -- tags not known by the API
  • DKIM_PARAM_SIGNATURE -- base64-encode signature data
  • DKIM_PARAM_SIGNALG -- DKIM signing algorithm
  • DKIM_PARAM_DOMAIN -- signing domain
  • DKIM_PARAM_CANONALG -- canonicalization algorithm(s)
  • DKIM_PARAM_QUERYMETHOD -- key lookup method
  • DKIM_PARAM_SELECTOR -- selector
  • DKIM_PARAM_HDRLIST -- colon-separated header list
  • DKIM_PARAM_VERSION -- version
  • DKIM_PARAM_IDENTITY -- sender's identity
  • DKIM_PARAM_TIMESTAMP -- signature timestamp
  • DKIM_PARAM_EXPIRATION -- signature expiration
  • DKIM_PARAM_COPIEDHDRS -- copied headers
  • DKIM_PARAM_BODYHASH -- body hash
  • DKIM_PARAM_BODYLENGTH -- body length
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_privkey_load.html000066400000000000000000000047571337314105200263010ustar00rootroot00000000000000 dkim_privkey_load()

dkim_privkey_load()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_privkey_load(
	DKIM *dkim
);
Attempt to load and prepare a private key for signing.
DESCRIPTION
Called When dkim_privkey_load() is called after dkim_sign() is called to create a message signing handle. It attemps to parse the key provided as an argument to that function and extract some parameters of it. This same operation will be done implicitly by dkim_eom() if not called explicitly beforehand.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign().
RETURN VALUES
  • DKIM_STAT_OK indicates the key was successfully parsed and loaded by the crypto library.
  • DKIM_STAT_NORESOURCE indicates the key could not be parsed.
NOTES
  • This library relies on a cryptography library to compute hashes and sign or verify them. It has been observed that different libraries have different levels of strictness about parsing keys provided to them. This is property is not under control of this library; this library merely responds to error codes that might be passed up from the crypto library.


Copyright (c) 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_qi_getname.html000066400000000000000000000041051337314105200257050ustar00rootroot00000000000000 dkim_qi_getname()

dkim_qi_getname()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_qi_getname(
	DKIM_QUERYINFO *query
);
Retrieve from a DKIM_QUERYINFO handle the name to be queried from the DNS.
DESCRIPTION
Called When dkim_qi_getname() can be called at any time after query information is returned by dkim_sig_getqueries().
ARGUMENTS
ArgumentDescription
query A reference to a DKIM_QUERYINFO handle.
RETURN VALUES
ValueDescription
NULL No name could be determined for this query handle.
otherwise A pointer to the DNS name found in the handle.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_qi_gettype.html000066400000000000000000000041261337314105200257510ustar00rootroot00000000000000 dkim_qi_gettype()

dkim_qi_gettype()

[back to index]

SYNOPSIS
#include <dkim.h>

int dkim_qi_gettype(
	DKIM_QUERYINFO *query
);
Retrieve from a DKIM_QUERYINFO handle the type to be used in performing the DNS query referenced by query.
DESCRIPTION
Called When dkim_qi_gettype() can be called at any time after query information is returned by dkim_sig_getqueries().
ARGUMENTS
ArgumentDescription
query A reference to a DKIM_QUERYINFO handle.
RETURN VALUES
ValueDescription
-1 No query type could be determined for this query handle.
otherwise A DNS resource record type.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_query_t.html000066400000000000000000000030201337314105200252570ustar00rootroot00000000000000 dkim_query_t

dkim_query_t

[back to index]

DESCRIPTION
Purpose A dkim_query_t is a value from an enumerated list of the possible key query algorithms available. It is typically determined by parsing the q= portion of a received signature when verifying an arriving message. However, by using dkim_options(), the caller can force a particular query method.
Possible Values
  • DKIM_QUERY_DNS -- use the DNS TXT record binding defined by the DKIM specification (the default)
  • DKIM_QUERY_FILE -- read keys from a local file; intended for debugging or experimental use only
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_queryinfo.html000066400000000000000000000024721337314105200256220ustar00rootroot00000000000000 DKIM_QUERYINFO

DKIM_QUERYINFO

[back to index]

DESCRIPTION
Purpose A DKIM_QUERYINFO handle stores data having to do with a DNS query that is or may be needed. This is useful when the application has some mechanism for resolving DNS queries that does not make direct use of the DNS handling system provided by libopendkim. It is created by the dkim_sig_getqueries() function and must be freed by the caller.
NOTES
  • More than one of these handles may exist at any given time.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_resign.html000066400000000000000000000101311337314105200250570ustar00rootroot00000000000000 dkim_resign()

dkim_resign()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_resign(
	DKIM *sh,
	DKIM *eh,
	bool hdrbind
);
Binds a signing handle to another handle to generate a second signature for a message being signed or verified. The message therefore only passes through the library once, but now produces either a verification result and a new signature, or multiple signatures.
DESCRIPTION
Called When dkim_resign() must be called after a signing handle is acquired with dkim_sign() and a separate (signing or verifying) handle is acquired with dkim_sign() or dkim_verify(), but before any message data has been passed to either one.
ARGUMENTS
ArgumentDescription
sh Message-specific handle, returned by dkim_sign(). It must not have been used to process any message data (i.e., no prior calls to dkim_header() or dkim_eoh().
eh Message-specific handle, returned by dkim_sign() or dkim_verify(). dkim_eoh() must not already have been called.
hdrbind If TRUE, indicates that both the header and the body of the message are bound to the verifying handle. If FALSE, only the body is bound, meaning the caller must provide a complete (but possibly different) set of header fields using dkim_header() prior to calling dkim_eoh().
RETURN VALUES One or more of the following:
  • sh is not a signing handle
  • eh has already been passed to dkim_eoh()
  • eh is already bound to another handle by a previous call to this function
ValueDescription
DKIM_STAT_OK The binding was successful.
DKIM_STAT_INVALID
NOTES

Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the license.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_dns_callback.html000066400000000000000000000054141337314105200270530ustar00rootroot00000000000000 dkim_set_dns_callback()

dkim_set_dns_callback()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_dns_callback(
	DKIM_LIB *libopendkim,
        void (*func)(const void *context),
        unsigned int interval);
);
Define a function which should be called from time to time while waiting for a DNS response to become available. This is particularly meant for use when libopendkim is being used by an application which is timeout-sensitive where a heartbeat ("still alive, operation in progress") message is desirable.

When defined, the specified function will be called at the specified interval even if the DNS response has not yet arrived, using the caller-specific context pointer set by the dkim_set_user_context() function (if any) as the parameter to that function.

DESCRIPTION
Called When dkim_set_dns_callback() can called at any time.
ARGUMENTS
ArgumentDescription
libopendkim Library-specific handle, returned by dkim_init().
func A pointer to a function which takes a single void pointer which should be called at the requested interval while waiting for a DNS reply. If NULL, no callback will be used.
interval Desired interval, in seconds, between calls to func.
RETURN VALUES
  • DKIM_STAT_OK -- the callback and interval were successfully registered
  • DKIM_STAT_NOTIMPLEMENT -- the underlying DNS resolution service does not provide a callback facility

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_final.html000066400000000000000000000107111337314105200255400ustar00rootroot00000000000000 dkim_set_final()

dkim_set_final()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_final(
	DKIM_LIB *libopendkim,
        DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs));
);
Defines a callback function to be used for final scanning and sorting of the signatures discovered on a message.

From within dkim_eoh(), an array of DKIM_SIGINFO handles is allocated, and an array of pointers is created referring to them. During dkim_eoh(), a prescreen callback may be used to do initial sorting, analysis and disqualification of discovered signatures.

If this callback function is defined, it will be called by dkim_eom() to give the caller a final opportunity to review the signatures and possibly reorder or flag them for special treatment by the library now that the entire body has arrived and body hashes can be computed. sigs will refer to the array of discovered signatures and nsigs will indicate the length of this array.

From within this callback you can use dkim_sig_getcontext() on any of the DKIM_SIGINFO pointers to retrieve the user-allocated context specific to that signature as created earlier by the allocation callback set by dkim_set_signature_handle() and make use of the data found there. That context is not used by the library in any way.

Also available are dkim_sig_getflags() to retrieve current processing flags assigned to a signature, dkim_sig_getbh() to retrieve the results of the body hash comparison done (if any) on the signature, and dkim_sig_process() to retrieve the key named by the signature and attempt public key verification and body hash comparison.

The callback can also use the function dkim_sig_ignore() to indicate to the library that the signature should be ignored.

The callback should return one of the DKIM_CBSTAT return values. Any other value will cause dkim_eoh() to abort and return a status of DKIM_STAT_CBINVALID.

DESCRIPTION
Called When dkim_set_final() must be called before dkim_eom() has been called.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function which takes a DKIM handle, a pointer to an array of DKIM_SIGINFO handles and an integer indicating the length of that array as parameters. If NULL, no callback will be used.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- dkim referred to a signing handle rather than a verifying handle
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_key_lookup.html000066400000000000000000000061631337314105200266360ustar00rootroot00000000000000 dkim_set_key_lookup()

dkim_set_key_lookup()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_key_lookup(
	DKIM_LIB *libopendkim,
        DKIM_CBSTAT (*func) (DKIM *dkim,
                             DKIM_SIGINFO *siginfo,
	                     unsigned char *buf,
	                     size_t buflen));
);
Defines a function which should do key lookups rather than implementing the DKIM specification (e.g., a DNS lookup). The query method specified in the signature will be ignored.
DESCRIPTION
Called When dkim_set_key_lookup() can be called at any time.
ARGUMENTS
ArgumentDescription
libopendkim Library-specific instance handle, returned by dkim_init().
func A pointer to a function which the library should use in place of its own code to do key lookups. The function will receive four things: A DKIM handle referencing the job being processed, a pointer to a DKIM_SIGINFO handle identifying the signature whose public key should be retrieved, a pointer to a buffer that should receive the result of the key lookup, and the number of bytes available there. The function should return an appropriate DKIM_CBSTAT return code after loading the buffer with its lookup result (if any). If func is NULL, the internal key lookup implementation, which will do what the signature requests, will be used.
RETURN VALUES
  • DKIM_STAT_OK -- success
NOTES
  • The callback should place into the provided buffer a NULL-terminated string formatted as a legal DKIM key record according to RFC6376 Section 3.6.1.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_margin.html000066400000000000000000000043441337314105200257310ustar00rootroot00000000000000 dkim_set_margin()

dkim_set_margin()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_margin(
	DKIM *dkim,
        int margin);
);
Specifies the margin to be enforced on the signature being generated. By default, the fixed value DKIM_HDRMARGIN (75) is used.
DESCRIPTION
Called When dkim_set_margin() can be called at any time prior to signature generation.
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign().
margin The desired margin. A value of 0 suppresses all line wrapping.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- dkim referred to a verifying header rather than a signing header, margin was negative, or dkim referred to a signing handle which has already been handled by dkim_eom()
NOTES
  • None.

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_prescreen.html000066400000000000000000000072171337314105200264440ustar00rootroot00000000000000 dkim_set_prescreen()

dkim_set_prescreen()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_prescreen(
	DKIM_LIB *libopendkim,
        DKIM_CBSTAT (*func)(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs));
);
Defines a callback function to be used for pre-scanning and sorting signatures discovered on a message.

From within dkim_eoh(), an array of DKIM_SIGINFO handles is allocated, and an array of pointers is created referring to them. If this callback function is defined, it will be called by dkim_eoh() to give the caller a chance to review the signatures and possibly reorder or flag them for special treatment by the library. sigs will refer to the array of discovered signatures and nsigs will indicate the length of this array.

From within the callback you can use dkim_sig_getcontext() on any of the DKIM_SIGINFO pointers to retrieve the user-allocated context specific to that signature as created earlier by the allocation callback set by dkim_set_signature_handle() and make use of the data found there. That context is not used by the library in any way.

The callback can also use the function dkim_sig_ignore() to indicate to the library that the signature should be completely ignored.

The callback should return one of the DKIM_CBSTAT return values. Any other value will cause dkim_eoh() to abort and return a status of DKIM_STAT_CBINVALID.

DESCRIPTION
Called When dkim_set_prescreen() must be called before dkim_eoh() has been called.
ARGUMENTS
ArgumentDescription
libopendkim The library instantiation handle, returned by dkim_init().
func A pointer to a function which takes a DKIM handle, a pointer to an array of DKIM_SIGINFO handles and an integer indicating the length of that array as parameters. If NULL, no callback will be used.
RETURN VALUES
  • DKIM_STAT_OK -- success
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_signature_handle.html000066400000000000000000000052131337314105200277640ustar00rootroot00000000000000 dkim_set_signature_handle()

dkim_set_signature_handle()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_signature_handle(
	DKIM_LIB *libopendkim,
        void * (*func)(void *closure));
);
Defines a callback function to be used for allocating local data storage to be associated with signatures.

From within dkim_eoh(), each discovered signature is assigned a DKIM_SIGINFO handle. If this callback function is defined, it will be called once for each such handle to allocate any caller-side storage that might be desired by the caller; the return value is assumed to be a pointer to such storage, and can be retrieved later by the caller during signature processing.

DESCRIPTION
Called When dkim_set_signature_handle() must be called before dkim_eoh() has been called.
ARGUMENTS
ArgumentDescription
libopendkim Library-specific handle, returned by dkim_init().
func A pointer to a function which takes a single void pointer that is the same as the memclosure passed to dkim_verify(). If NULL, no callback will be used.
RETURN VALUES
  • DKIM_STAT_OK -- success
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_signature_handle_free.html000066400000000000000000000053741337314105200307750ustar00rootroot00000000000000 dkim_set_signature_handle_free()

dkim_set_signature_handle_free()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_signature_handle_free(
	DKIM_LIB *libopendkim,
        void (*func)(void *closure, void *ptr));
);
Defines a callback function to be used for deallocating local data storage to be associated with signatures.

When destroying a DKIM_SIGINFO handle, any user space allocated by a call to the callback set by dkim_set_signature_handle_free() must also be deallocated. If this callback function is defined, it will be called once for each such handle to deallocate any caller-side storage that was previously allocated.

DESCRIPTION
Called When dkim_set_signature_handle_free() can be called at any time.
ARGUMENTS
ArgumentDescription
libopendkim Library-specific handle, returned by dkim_init().
func A pointer to a function which takes a two void pointers; the first is the same as the memclosure passed to dkim_verify(), and the second is the pointer previously returned by a call to the callback set by dkim_set_signature_handle(). If NULL, no callback will be used.
RETURN VALUES
  • DKIM_STAT_OK -- success
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_signature_tagvalues.html000066400000000000000000000061711337314105200305300ustar00rootroot00000000000000 dkim_set_signature_tagvalues()

dkim_set_signature_tagvalues()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_signature_tagvalues(
	DKIM_LIB *libopendkim,
        void (*func)(void *user,
	             dkim_param_t pcode,
	             const unsigned char *param,
	             const unsigned char *value);
);
Defines a callback function to be used for providing signature tag/value pairs to the calling program for local processing.

From within dkim_eoh(), each discovered signature is assigned a DKIM_SIGINFO handle. Using a callback, the caller can arrange to allocate caller-side storage that might be desired by the caller for processing signatures; the return value from that callback is assumed to be a pointer to such storage. The callback defined here will be invoked once for each tag-value pair found in each signature, thus providing that data to the caller for any desirable local processing. The data thus provided are read-only.

DESCRIPTION
Called When dkim_set_signature_tagvalues() must be called before dkim_eoh() has been called.
ARGUMENTS
ArgumentDescription
libopendkim Library-specific handle, returned by dkim_init().
func A pointer to a function which takes four parameters:
  • user is the caller-side handle pointer generated by the earlier callback; this will be the same pointer each time a tag-value pair is passed in for the same signature
  • pcode is an integer code indicating which parameter is being provided (useful for C "switch" statements)
  • param is a pointer to the name of the tag being provided
  • value is a pointer to the value of the tag being provided
If NULL, no callback will be used.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_signer.html000066400000000000000000000046151337314105200257440ustar00rootroot00000000000000 dkim_set_signer()

dkim_set_signer()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_signer(
	DKIM *dkim,
        const unsigned char *signer);
);
Specifies the signer to be included in the signature being generated. This will cause the "i=" tag to be added to the signature when it gets generated.
DESCRIPTION
Called When dkim_set_signer() can be called at any time prior to signature generation.
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign().
signer A pointer to a null-terminated string which specifies the entity which is responsible for the signature being generated. This will cause an "i=" tag containing this value to be included in the signature generated by this handle. If not defined, no "i=" tag will be added, meaning verifiers should use an implied value.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- dkim referred to a verifying header rather than a signing header
  • DKIM_STAT_NORESOURCE -- out of memory
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_trust_anchor.html000066400000000000000000000044371337314105200271720ustar00rootroot00000000000000 dkim_set_trust_anchor()

dkim_set_trust_anchor()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_trust_anchor(
	DKIM_LIB *lib,
        char *tafile);
);
Sets the path to a local trust anchor file, used when doing DNSSEC evaluations.
DESCRIPTION
Called When dkim_set_trust_anchor() can be called at any time after initializing the library with dkim_init() but prior to any DNS operations done during verifying.
ARGUMENTS
ArgumentDescription
lib Library-specific context handle created by a call to dkim_init().
tafile A pointer to a character string identifying the trust anchor file to be used when performing DNSSEC queries.
RETURN VALUES
  • DKIM_STAT_OK -- success
  • DKIM_STAT_INVALID -- the trust anchor file could not be used
  • DKIM_STAT_NOTIMPLEMENT -- the underlying DNS system used when the library was compiled did not have DNSSEC support
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_set_user_context.html000066400000000000000000000047741337314105200272050ustar00rootroot00000000000000 dkim_set_user_context()

dkim_set_user_context()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_set_user_context(
	DKIM *dkim,
        void *ctx);
);
Specifies an opaque user context pointer to be passed to the DNS callback set by dkim_set_dns_callback(), if any.
DESCRIPTION
Called When dkim_set_user_context() can be called at any time prior to DNS operations while verifying.
ARGUMENTS
ArgumentDescription
dkim Message-specific signing handle, returned by dkim_sign() or dkim_verify(). Note that since DNS operations only take place while verifying, this is really only meaningful in the latter case.
ctx A pointer to a user-generated context handle referencing data specific to the message being signed or verified by the handle provided above.
RETURN VALUES
  • DKIM_STAT_OK -- success
NOTES
  • The context pointer, if set, will be passed as-is to the DNS callback, if any. It can also be retrieved by the caller at any time using the dkim_get_user_context() function.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_setpartial.html000066400000000000000000000046771337314105200257620ustar00rootroot00000000000000 dkim_setpartial()

dkim_setpartial()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_setpartial(
	DKIM *dkim,
	_Bool value
);
DESCRIPTION
Called When dkim_setpartial() can be called at any time after a DKIM handle has been initialized by dkim_sign().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign().
value Either TRUE or FALSE, indicating wether or not the message being processed should have a signature generated with the "l=" tag.
RETURN VALUES
ValueDescription
DKIM_STAT_OK Successful completion.
DKIM_STAT_INVALID The message-specific handle is not a signing handle.
NOTES
  • Regardless if the setting of this bit inside a message-specific handle, a signature with "l=" will be generated if the DKIM_LIBFLAGS_SIGNLEN flag was set on the library handle.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getbh.html000066400000000000000000000045011337314105200255270ustar00rootroot00000000000000 dkim_sig_getbh()

dkim_sig_getbh()

[back to index]

SYNOPSIS
#include <dkim.h>

int dkim_sig_getbh(
	DKIM_SIGINFO *sig
);
Retrieve the body hash test status stored for a specific signature.
DESCRIPTION
Called When dkim_sig_getbh() can be called in the final callback, if defined, or after dkim_eom().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
RETURN VALUE The value returned is one of the following constants:
Constant NameDescription
DKIM_SIGBH_UNTESTED The signature has not yet been tested for a body hash match.
DKIM_SIGBH_MATCH The signature has been tested for a body hash match and the test succeeded.
DKIM_SIGBH_MISMATCH The signature has been tested for a body hash match and the test failed.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getcanonlen.html000066400000000000000000000100671337314105200267370ustar00rootroot00000000000000 dkim_sig_getcanonlen()

dkim_sig_getcanonlen()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getcanonlen(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
        ssize_t *msglen,
        ssize_t *canonlen,
        ssize_t *signlen
);
Retrieve the number of bytes of message body presented for signing or verifying, and/or the number of bytes actually signed or verified.
DESCRIPTION
Called When dkim_sig_getcanonlen() is called after dkim_eom() to get the number of bytes of message body presented for signing or verifying, and/or the number of bytes actually signed or verified. This is used to allow a verifier to insist on minimum signing volumes or percentages (e.g., a verifier may decide not to trust a message which was only partially signed).
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify.
sig The DKIM_SIGINFO handle representing the signature being evaluated.
msglen A pointer to an ssize_t which will receive a count of the number of bytes in the canonicalized form of the message. This should always be the number of bytes in the message body plus or minus whatever was required to canonicalize it (so for "simple" canonicalization it should be roughly the exact byte count, while for "relaxed" canonicalization it should be somewhat less). Can be NULL if this information is not needed by the caller.
canonlen A pointer to an ssize_t which will receive a count of the number of bytes in the canonicalized form of the message that were included in the signed data. If msglen and canonlen are the same, then the entire message was signed. If it is less, then the signer didn't sign the entire message. A verifier can compare this value with that of msglen to see what portion of the total message was signed by the signer. Note that msglen and canonlen can differ even if no signature length limit was set if, for example, there were trailing blank lines on the message as these are always stripped. Can be NULL if this information is not needed by the caller.
signlen A pointer to an ssize_t which will receive the signature length limit for this signature (i.e. the value of the "l=" tag if one was present on the signature). If no limit was set by the signer, a value of -1 is returned. Can be NULL if this information is not needed by the caller.
NOTES
  • None.

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getcanons.html000066400000000000000000000045371337314105200264300ustar00rootroot00000000000000 dkim_sig_getcanons()

dkim_sig_getcanons()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getcanons(
	DKIM_SIGINFO *sig,
        dkim_canon_t *hdr,
        dkim_canon_t *body
);
Retrieve the canonicalizations used to apply a signature to a message.
DESCRIPTION
Called When dkim_sig_getcanons() is called after dkim_eoh() to get the header and body canonicalization modes used to sign a message.
ARGUMENTS
ArgumentDescription
sig The DKIM_SIGINFO handle representing the signature being evaluated.
hdr A pointer to a dkim_canon_t which will receive the header canonicalization mode used when generating the provided signature. Can be NULL if this information is not needed by the caller.
body A pointer to a dkim_canon_t which will receive the body canonicalization mode used when generating the provided signature. Can be NULL if this information is not needed by the caller.
NOTES
  • None.

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getcontext.html000066400000000000000000000031271337314105200266250ustar00rootroot00000000000000 dkim_sig_getcontext()

dkim_sig_getcontext()

[back to index]

SYNOPSIS
#include <dkim.h>

void * dkim_sig_getcontext(
	DKIM_SIGINFO *sig
);
Retrieve the user-provided context pointer for a specific signature.
DESCRIPTION
Called When dkim_sig_getcontext() can be called from within the prescreen callback, if defined.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle, passed to the prescreen callback (if defined).
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getdnssec.html000066400000000000000000000036501337314105200264210ustar00rootroot00000000000000 dkim_sig_getdnssec()

dkim_sig_getdnssec()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_DNSSEC dkim_sig_getdnssec(
	DKIM_SIGINFO *sig
);
Retrieve DNSSEC information about the DNS query that was used to retrieve the key matching a signature. The value returned is a DKIM_DNSSEC constant.
DESCRIPTION
Called When dkim_sig_getdnssec() is called after dkim_eoh() to determine whether or not DNSSEC was used to retrieve the key matching the provided signature, and if so, whether or not the returned value was legitimate.
ARGUMENTS
ArgumentDescription
sig The DKIM_SIGINFO handle representing the signature being evaluated.
NOTES
  • None.

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getdomain.html000066400000000000000000000041021337314105200264020ustar00rootroot00000000000000 dkim_sig_getdomain()

dkim_sig_getdomain()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_sig_getdomain(
	DKIM_SIGINFO *sig
);
Retrieve from a DKIM handle the domain name associated with the signature on a message.
DESCRIPTION
Called When dkim_sig_getdomain() can be called at any time after signature handles are initialized by a call to dkim_eoh().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
RETURN VALUES
ValueDescription
NULL No domain name could be determined for this signature.
otherwise A pointer to the domain name found in the signature.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_geterror.html000066400000000000000000000032311337314105200262660ustar00rootroot00000000000000 dkim_sig_geterror()

dkim_sig_geterror()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_SIGERROR dkim_sig_geterror(
	DKIM_SIGINFO *sig
);
Retrieve the error value stored for a specific signature.
DESCRIPTION
Called When dkim_sig_geterror() can be called from within the prescreen or final or callbacks, if defined.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_geterrorstr.html000066400000000000000000000030651337314105200270240ustar00rootroot00000000000000 dkim_sig_geterrorstr()

dkim_sig_geterrorstr()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_sig_geterrorstr(
	DKIM_SIGERROR sigerr
);
Retrieve a string describing a signature error code, or NULL if the code had no text translation.
DESCRIPTION
Called When dkim_sig_geterrorstr() can be called at any time.
ARGUMENTS
ArgumentDescription
sigerr A DKIM_SIGERROR constant.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getflags.html000066400000000000000000000057741337314105200262470ustar00rootroot00000000000000 dkim_sig_getflags()

dkim_sig_getflags()

[back to index]

SYNOPSIS
#include <dkim.h>

unsigned int dkim_sig_getflags(
	DKIM_SIGINFO *sig
);
Retrieve the flags stored for a specific signature.
DESCRIPTION
Called When dkim_sig_getflags() can be called in the prescreen or final or callbacks, if defined, or after dkim_eoh().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
RETURN VALUE The value returned is a bitwise-OR of the following constants:
Flag NameDescription
DKIM_SIGFLAG_IGNORE The signature has been flagged to be ignored by a prior call to dkim_sig_ignore().
DKIM_SIGFLAG_PROCESSED The signature has had DNS validation attempted.
DKIM_SIGFLAG_PASSED DNS validation succeeded. See NOTES below.
DKIM_SIGFLAG_TESTKEY Key's "in test" flag was set.
DKIM_SIGFLAG_NOSUBDOMAIN Key's "not for use with subdomains" flag was set.
NOTES
  • The DKIM_SIGFLAG_PASSED flag is set if the header hash, the public key and the digital signature resulted in a successful verification. It does not reflect whether the computed body hash matched the one found in the signature. It is necessary for the caller to use the dkim_sig_getbh() as well to test for that case.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_gethashes.html000066400000000000000000000050251337314105200264130ustar00rootroot00000000000000 dkim_sig_gethashes()

dkim_sig_gethashes()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_sig_gethashes(
	DKIM_SIGINFO *sig,
	void **hh,
	size_t *hhlen,
	void **bh,
	size_t *bhlen
);
Retrieve the hashes associated with a signature.
DESCRIPTION
Called When dkim_sig_gethashes() can be called after dkim_eom has completed.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
hh A void pointer that will be updated to point to the location in memory of the header hash (in binary form).
hhlen A pointer to a size_t that will be updated to contain the number of bytes consumed by the header hash.
bh A void pointer that will be updated to point to the location in memory of the body hash (in binary form).
bhlen A pointer to a size_t that will be updated to contain the number of bytes consumed by the body hash.
RETURN VALUE
  • DKIM_STAT_OK -- successful completion
  • DKIM_STAT_INVALID -- the function was called before dkim_eom() was called, meaning the hashes have not yet been finalized
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getidentity.html000066400000000000000000000050131337314105200267660ustar00rootroot00000000000000 dkim_sig_getidentity()

dkim_sig_getidentity()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getidentity(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
        char *val,
        size_t vallen
);
Retrieve the signing identity from a signature handle.
DESCRIPTION
Called When dkim_sig_getidentity() is called after dkim_eoh() to determine the identity associated with a signature.
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_sign() or dkim_verify.
sig The DKIM_SIGINFO handle representing the signature being evaluated.
val A character buffer to receive the identity extracted from the signature. The value may be explicitly defined in the signature's "i=" tag, or inferred from its absence.
vallen Number of bytes available at val.
RETURN VALUES
  • DKIM_STAT_OK -- successful completion
  • DKIM_STAT_SYNTAX -- some part of the input string was invalid
  • DKIM_STAT_NORESOURCE -- val did not contain enough space for the complete identity string

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010 The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getkeysize.html000066400000000000000000000050501337314105200266210ustar00rootroot00000000000000 dkim_sig_getkeysize()

dkim_sig_getkeysize()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getkeysize(
	DKIM_SIGINFO *sig,
        unsigned int *bits
);
Retrieve the number of bits in the key used to verify a message.
DESCRIPTION
Called When dkim_sig_getkeysize() is called after the signature handle has been processed by either an explicit call to dkim_sig_process() or the completion of dkim_eom() to get the number of bits in the key used to validate a message.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
bits A pointer to an unsigned int which will receive the number of bits in the key used to verify the message.
RETURN VALUES
ValueDescription
DKIM_STAT_INVALID The function was called before the signature was processed either explicitly by dkim_sig_process(), or implicitly by dkim_eom().
DKIM_STAT_OK Successful completion.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getqueries.html000066400000000000000000000055771337314105200266310ustar00rootroot00000000000000 dkim_sig_getqueries()

dkim_sig_getqueries()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_sig_getqueries(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
	DKIM_QUERYINFO ***qi,
	unsigned int *nqi
);
Given a signature handle, return the DNS query or queries that would be required to complete verification of that signature.
DESCRIPTION
Called When dkim_sig_getqueries() can be called at any time after signature handles are completely received and stored via a call to dkim_eoh().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, previously returned by dkim_verify().
sig Signature-specific handle, acquired from dkim_getsiglist().
qi An array of DKIM_QUERYINFO handles allocated by the the library to return the set of required DNS queries.
nqi The number of elements in the qi array.
RETURN VALUES
ValueDescription
DKIM_STAT_NORESOURCE Memory could not be allocated for the new array.
DKIM_STAT_OK The array was allocated and returned.
NOTES
  • The caller is responsible for deallocating the array and each element of it returned function.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getreportinfo.html000066400000000000000000000106631337314105200273330ustar00rootroot00000000000000 dkim_sig_getreportinfo()

dkim_sig_getreportinfo()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getreportinfo(
	DKIM *dkim,
	DKIM_SIGINFO *sig,
        int *hfd,
        int *bfd,
        char *addrbuf,
        size_t addrlen,
        char *optsbuf,
        size_t optslen,
        char *smtpbuf,
        size_t smtplen,
	u_int *interval
);
Retrieve information required to generate a signature verification failure report. The calling application can use this information to generate an ARF (Abuse Reporting Format) or other report for use in determining the cause of interoperability problems between implementations.
DESCRIPTION
Called When dkim_sig_getreportinfo() is called after dkim_eom() when dkim is a verifying handle, i.e. one returned by an earlier call to dkim_verify().
ARGUMENTS
ArgumentDescription
dkim Message-specific handle, returned by dkim_verify. May not be NULL.
sig A pointer to a DKIM_SIGINFO handle about which a report should be generated. May not be NULL.
hfd A pointer to an integer that will be updated to contain a file descriptor referencing a file which contains the canonicalized version of the message headers that failed to verify. Can be NULL if this information is not needed by the caller.
bfd A pointer to an integer that will be updated to contain a file descriptor referencing a file which contains the canonicalized version of the message body that failed to verify. Can be NULL if this information is not needed by the caller.
addrbuf A buffer into which the destination address of the report, as extracted from the domain's key record, will be written. Can be NULL if this information is not needed by the caller. Note that this only contains the local-part of the address; the domain should be extracted from the signature which failed.
addrlen Number of bytes available at addrbuf.
optsbuf A buffer into which a colon-separated list of report options desired by the requesting domain will be written. This is copied exactly as extracted from the domain's key record. Can be NULL if this information is not needed by the caller.
optslen Number of bytes available at optsbuf.
smtpbuf A buffer into which the sender-requested SMTP error prefix string, if any, will be written. This is copied exactly as extracted from the domain's key record. Can be NULL if this information is not needed by the caller.
smtplen Number of bytes available at smtpbuf.
interval Requested report interval. Can be NULL if this information is not needed by the caller.
NOTES
  • None.

Copyright (c) 2005, 2007, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getselector.html000066400000000000000000000041421337314105200267570ustar00rootroot00000000000000 dkim_sig_getselector()

dkim_sig_getselector()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_sig_getselector(
	DKIM_SIGINFO *sig
);
Retrieve from a DKIM handle the selector name associated with the specified signature on a message.
DESCRIPTION
Called When dkim_sig_getselector() can be called at any time after the signature information handles are initialized in the call to dkim_eoh().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
RETURN VALUES
ValueDescription
NULL No selector could be determined for this signature.
otherwise A pointer to the selector found in the signature.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getsignalg.html000066400000000000000000000047721337314105200265740ustar00rootroot00000000000000 dkim_sig_getsignalg()

dkim_sig_getsignalg()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getsignalg(
	DKIM_SIGINFO *sig,
        dkim_alg_t *alg
);
Retrieve the signature algorithm used to sign a message after verification.
DESCRIPTION
Called When dkim_sig_getsignalg() is called after a signature is processed either explicitly by a call to dkim_sig_process() or by dkim_eom() to get the signing algorithm that was used to sign a message.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
alg A pointer to a dkim_alg_t which will receive the algorithm that was used to sign the message.
RETURN VALUES
ValueDescription
DKIM_STAT_INVALID The function was called before dkim_sig_process() or dkim_eom() processed the siganture.
DKIM_STAT_OK Successful completion.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getsignedhdrs.html000066400000000000000000000072111337314105200272710ustar00rootroot00000000000000 dkim_sig_getsignedhdrs()

dkim_sig_getsignedhdrs()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_sig_getsignedhdrs(
	DKIM *DKIM,
	DKIM_SIGINFO *sig,
        unsigned char *hdrs,
	size_t hdrlen,
        unsigned int *nhdrs
);
Retrieve from a DKIM and signature handle the set of header fields that were included in the hashes of a valid signature.
DESCRIPTION
Called When dkim_sig_getsignedhdrs() can be called at any time after signature validation is completed via a call to dkim_eom() using a DKIM handle that was created by dkim_verify(). Only a signature that fully validated is acceptable.
ARGUMENTS
ArgumentDescription
dkim A message validation handle previously created using dkim_verify().
sig Signature-specific handle.
hdrs An array of fixed-length character strings that should be filled by header fields that were included in this signature's header hash.
hdrlen The number of bytes available in each element of the hdrs array.
nhdrs This should contain a pointer to the number of elements available in the hdrs array. It will be updated to contain the number of header fields that were included in the signature. If insufficient array elements were available, the array will not be updated (but this value will) and an error code is returned. If temporary memory could not be acquired, this value will be set to zero and an error will be returned.
RETURN VALUES
ValueDescription
DKIM_STAT_INTERNAL An internal error occurred.
DKIM_STAT_NORESOURCE The hdrs array was too small to contain the result, or not enough temporary memory could be allocated. If on return from this function nhdrs contains 0, the latter occurred; otherwise, nhdrs will be updated to contain the size of the array needed to get all the data out.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getsigntime.html000066400000000000000000000050331337314105200267560ustar00rootroot00000000000000 dkim_sig_getsigntime()

dkim_sig_getsigntime()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM_STAT dkim_sig_getsigntime(
	DKIM_SIGINFO *sig,
        uint64_t *when
);
Retrieve the signature timestamp used to sign a message after verification.
DESCRIPTION
Called When dkim_sig_getsigntime() is called after either an explicit call to dkim_sig_process() or completion of dkim_eom() to get the timestamp included in the signature of a message.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
time A pointer to a uint64_t that will receive the timestamp of the signature on the message. The value is computed the same way as a time_t, but allows for larger integers.
RETURN VALUES
ValueDescription
DKIM_STAT_INVALID The signature referenced by the DKIM_SIGINFO handle did not contain a signature with a timestamp.
DKIM_STAT_OK Successful completion.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_getsslbuf.html000066400000000000000000000042031337314105200264330ustar00rootroot00000000000000 dkim_sig_getsslbuf()

dkim_sig_getsslbuf()

[back to index]

SYNOPSIS
#include <dkim.h>

const char * dkim_sig_getsslbuf(
	DKIM_SIGINFO *sig
);
Retrieve from a DKIM signature handle SSL error buffer, which will contain the SSL-specific error string, if any.
DESCRIPTION
Called When dkim_sig_getsslbuf() can be called at any time after the cryptographic phase of signature processing has occurred, i.e., after dkim_eoh().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
RETURN VALUES
ValueDescription
NULL No error message was recorded.
otherwise A pointer to the SSL error message recorded for the provided signature handle.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_gettagvalue.html000066400000000000000000000046431337314105200267550ustar00rootroot00000000000000 dkim_sig_gettagvalue()

dkim_sig_gettagvalue()

[back to index]

SYNOPSIS
#include <dkim.h>
unsigned char *dkim_sig_gettagvalue(
	DKIM_SIGINFO *sig,
        _Bool keytag,
        char *tag
);
Retrieve the raw value of a signature or key tag.
DESCRIPTION
Called When dkim_sig_gettagvalue() is called after dkim_eoh() when dkim is a verifying handle, i.e. one returned by an earlier call to dkim_verify().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle, returned by dkim_getsiglist. May not be NULL.
keytag If TRUE, indicates that the tag of interest can be found in the key record associated with the signature. If FALSE, the tag of interest is expected to be within the signature itself.
tag A pointer to a string containing the name of the tag of interest. May not be NULL.
NOTES
  • The data thus returned has not necessarily been processed for validity or safety. Exercise caution.
  • This interface was added to support the collection of statistics about DKIM use, and is not intended for general use by applications.

Copyright (c) 2005, 2007, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_hdrsigned.html000066400000000000000000000050311337314105200264040ustar00rootroot00000000000000 dkim_sig_hdrsigned()

dkim_sig_hdrsigned()

[back to index]

SYNOPSIS
#include <dkim.h>

bool dkim_sig_hdrsigned(
	DKIM_SIGINFO *sig,
	char *hdr
);
Determine whether or not a particular header was covered by a specific signature on a message.
DESCRIPTION
Called When dkim_sig_hdrsigned() can be called at any time after headers have been processed for a message being signed or verified, essentially after a call to dkim_eoh().
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
hdr The name of the header to be checked.
RETURN VALUES
ValueDescription
TRUE The header named by hdr was included in the signature referenced by sig.
FALSE sig did not cover hdr.
NOTES
  • The check performed by this function is fairly simple: it will see if hdr appears in the "h=" tag for the signature identified by sig. It does not guarantee that a specific instance of that header was signed, which is relevant for headers that appear more than once (e.g. Received:).

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_ignore.html000066400000000000000000000030571337314105200257260ustar00rootroot00000000000000 dkim_sig_ignore()

dkim_sig_ignore()

[back to index]

SYNOPSIS
#include <dkim.h>

void dkim_sig_ignore(
	DKIM_SIGINFO *sig
);
Flag a signature to be ignored by the library.
DESCRIPTION
Called When dkim_sig_ignore() can be called from within the prescreen callback, if defined.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle, passed to the prescreen callback (if defined).
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_process.html000066400000000000000000000070661337314105200261250ustar00rootroot00000000000000 dkim_sig_process()

dkim_sig_process()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_sig_process(
	DKIM *dkim,
	DKIM_SIGINFO *sig
);
Runs verification on a signature, returning a result. The function will retrieve the key needed to verify the signature if that hasn't already been done, and if called from the final callback, compare the computed body hash to the one found in the signature.

Upon completion of processing of the signature, the caller may use dkim_sig_getflags() and dkim_sig_getbh() to retrieve the results of the processing.

DESCRIPTION
Called When dkim_sig_process() can be called from within the user prescreen or final callbacks, if defined.
ARGUMENTS
ArgumentDescription
dkim DKIM handle, returned by a prior call to dkim_verify().
sig Signature-specific handle generated by the library.
RETURN VALUES
Return ValueDescription
DKIM_STAT_OK Signature processing was completed.
DKIM_STAT_NORESOURCE The library was unable to create one or more data structures required to complete the processing.
DKIM_STAT_CBERROR
DKIM_STAT_CBINVALID
DKIM_STAT_CBREJECT
DKIM_STAT_CBTRYAGAIN
A registered lookup callback returned a non-completion result. See DKIM_STAT for further details.
NOTES
  • A positive result from dkim_sig_getflags() after calling this function during the prescreen callback is not sufficient to conclude that the signature is good, since at that time a final result from dkim_sig_getbh() is not available. The latter must be tested in the final callback to ensure that the signature was good and the signature's body hash matched the one computed by the library.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_setdnssec.html000066400000000000000000000034221337314105200264320ustar00rootroot00000000000000 dkim_sig_setdnssec()

dkim_sig_setdnssec()

[back to index]

SYNOPSIS
#include <dkim.h>

void dkim_sig_setdnssec(
	DKIM_SIGINFO *sig,
	int dnssec_status
);
Store the DNSSEC result for a specified signature.
DESCRIPTION
Called When dkim_sig_setdnssec() can be called by any caller-provided DNS function to indicate the result of DNSSEC evaluation of a key record.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
dnssec_status A valid DNSSEC result code. any unrecognized value will be treated as DKIM_DNSSEC_UNKNOWN.
NOTES
  • None.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_seterror.html000066400000000000000000000036151337314105200263100ustar00rootroot00000000000000 dkim_sig_seterror()

dkim_sig_seterror()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_sig_seterror(
	DKIM_SIGINFO *sig,
	int err
);
Set the error value stored for a specific signature.
DESCRIPTION
Called When dkim_sig_seterror() can be called from within the key lookup callback set by dkim_set_key_lookup(), if defined.
ARGUMENTS
ArgumentDescription
sig Signature-specific handle.
err A DKIM_SIGERROR error code.
NOTES
  • Returns DKIM_STAT_INVALID if the signature already has an error code assigned to it other than DKIM_SIGERROR_UNKNOWN.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sig_syntax.html000066400000000000000000000043741337314105200257740ustar00rootroot00000000000000 dkim_sig_syntax()

dkim_sig_syntax()

[back to index]

SYNOPSIS
#include <dkim.h>

DKIM_STAT dkim_sig_syntax(
	DKIM *dkim,
	unsigned char *str,
	size_t len
);
Validates the syntax of a signature header, returning a result. The signature is not stored or used, only validated.

DESCRIPTION
Called When dkim_sig_syntax() can be called at any time.
ARGUMENTS
ArgumentDescription
dkim DKIM handle, returned by a prior call to dkim_sign() or dkim_verify().
str Pointer to a buffer containing the signature to be evaluated.
len Number of bytes available at str.
RETURN VALUES
Return ValueDescription
DKIM_STAT_OK The signature appeared to be syntactically valid.
DKIM_STAT_SYNTAX The signature did not appear to be syntactically valid.

Copyright (c) 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sigerror.html000066400000000000000000000102121337314105200254240ustar00rootroot00000000000000 DKIM_SIGERROR

DKIM_SIGERROR

[back to index]

DESCRIPTION
Purpose A DKIM_SIGERROR is a mnemonic describing a problem found when processing a DKIM signature. More than one problem may exist in a signature; only one is reported per attempt to process it.
Possible Values
  • DKIM_SIGERROR_UNKNOWN -- unspecified error
  • DKIM_SIGERROR_OK -- no problems detected
  • DKIM_SIGERROR_VERSION -- incompatible/unsupported version
  • DKIM_SIGERROR_DOMAIN -- signing domain and signing identity do not match
  • DKIM_SIGERROR_EXPIRED -- signature has expired
  • DKIM_SIGERROR_FUTURE -- timestamp on signature is in the future
  • DKIM_SIGERROR_TIMESTAMPS -- expiration time is before signature time
  • DKIM_SIGERROR_INVALID_HC -- invalid/unsupported header canonicalization
  • DKIM_SIGERROR_INVALID_BC -- invalid/unsupported body canonicalization
  • DKIM_SIGERROR_MISSING_A -- signature algorithm missing
  • DKIM_SIGERROR_INVALID_A -- invalid/unsupported signature algorithm
  • DKIM_SIGERROR_MISSING_H -- header list missing
  • DKIM_SIGERROR_INVALID_L -- body length invalid
  • DKIM_SIGERROR_INVALID_Q -- invalid/unsupported query method
  • DKIM_SIGERROR_INVALID_QO -- invalid/unsupported query option
  • DKIM_SIGERROR_MISSING_D -- signing domain missing
  • DKIM_SIGERROR_EMPTY_D -- signing domain empty
  • DKIM_SIGERROR_MISSING_S -- selector missing
  • DKIM_SIGERROR_EMPTY_S -- selector empty
  • DKIM_SIGERROR_MISSING_B -- signature missing
  • DKIM_SIGERROR_EMPTY_B -- signature empty
  • DKIM_SIGERROR_CORRUPT_B -- signature corrupt
  • DKIM_SIGERROR_NOKEY -- key not found in DNS
  • DKIM_SIGERROR_DNSSYNTAX -- DNS reply corrupt
  • DKIM_SIGERROR_KEYFAIL -- DNS query error
  • DKIM_SIGERROR_MISSING_BH -- missing body hash
  • DKIM_SIGERROR_EMPTY_BH -- empty body hash
  • DKIM_SIGERROR_CORRUPT_BH -- corrupt body hash
  • DKIM_SIGERROR_BADSIG -- signature failed to verify
  • DKIM_SIGERROR_SUBDOMAIN -- signature violated SSP regarding subdomains
  • DKIM_SIGERROR_MULTIREPLY -- multiple DNS replies were returned
  • DKIM_SIGERROR_EMPTY_H -- header list was empty
  • DKIM_SIGERROR_INVALID_H -- header list missing required entries
  • DKIM_SIGERROR_TOOLARGE_L -- length tag value exceeds body size
  • DKIM_SIGERROR_MBSFAILED -- a header on the "must be signed" list was present but not covered by this signature
  • DKIM_SIGERROR_KEYVERSION -- unknown key version
  • DKIM_SIGERROR_KEYUNKNOWNHASH -- unknown key hash
  • DKIM_SIGERROR_KEYHASHMISMATCH -- signature-key hash mismatch
  • DKIM_SIGERROR_NOTEMAILKEY -- not an e-mail key
  • DKIM_SIGERROR_KEYTYPEMISSING -- key type missing
  • DKIM_SIGERROR_KEYTYPEUNKNOWN -- unknown key type
  • DKIM_SIGERROR_KEYREVOKED -- key revoked
  • DKIM_SIGERROR_KEYDECODE -- unable to decode public key
  • DKIM_SIGERROR_MISSING_V -- missing version
  • DKIM_SIGERROR_EMPTY_V -- empty version
  • DKIM_SIGERROR_KEYTOOSMALL -- signing key did not meet minimum size requirements

Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_siginfo.html000066400000000000000000000024661337314105200252420ustar00rootroot00000000000000 DKIM_SIGINFO

DKIM_SIGINFO

[back to index]

DESCRIPTION
Purpose A DKIM_SIGINFO handle stores data having to do with a signature handle discovered during a verification operation. A DKIM handle contains an array of these items, one for each signature discovered on an arriving message. It also contains an optional pointer to user-specific data which can be retrieved by the user during signature processing operations.
NOTES
  • More than one of these handles may exist at any given time.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sigkey_t.html000066400000000000000000000025351337314105200254170ustar00rootroot00000000000000 dkim_sigkey_t

dkim_sigkey_t

[back to index]

DESCRIPTION
Purpose A dkim_sigkey_t points to the private key to be used to sign messages. It should be a contiguous block of memory containing the private key either in PEM format, or in base64-encoded DER format, terminated by a NUL character. (For now, it is simply a pointer to a string of type unsigned char.)
NOTES
  • The calling application should read the key into memory and pass it in as this data type. Carriage return and newline characters (ASCII 13 and 10, respectively) need not be stripped.

Copyright (c) 2005 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_sign.html000066400000000000000000000104461337314105200245410ustar00rootroot00000000000000 dkim_sign()

dkim_sign()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM *dkim_sign(
	DKIM_LIB *libhandle,
	const char *id,
	void *memclosure,
	const unsigned char *secretkey,
	const unsigned char *selector,
	const unsigned char *domain,
	dkim_canon_t hdrcanon_alg,
	dkim_canon_t bodycanon_alg,
	dkim_alg_t sign_alg,
	ssize_t length
	DKIM_STAT *statp
);
Create a new handle for signing a message.
DESCRIPTION
Called When dkim_sign() is called when preparing to process a new message that will be signed later by a private key.
ARGUMENTS
ArgumentDescription
libhandle DKIM library instance handle, returned by an earlier call to dkim_init().
id An opaque, printable string for identifying this message, suitable for use in logging or debug output.
memclosure Opaque memory closure, passed directly to the caller-provided malloc() and/or free() replacement functions.
secretkey The private key to be used when signing this message. This must be a NULL-terminated string containing either a PEM-formatted private key, or a DER-formatted private key after being encoded with base64.
selector The name of the selector to be reported in the signature on this message.
domain The domain doing the signing; this will be the domain whose DNS will be queried by the verifier for key data.
hdrcanon_alg The canonicalization algorithm to use when preparing the headers of this message for signing.
bodycanon_alg The canonicalization algorithm to use when preparing the body of this message for signing.
sign_alg The signing algorithm to use when generating the signature to be attached to this message.
length The number of bytes of the body to sign. A value of -1 will cause the entire message to be signed.
statp Pointer to a DKIM_STAT object which receives the completion status of this operation.
NOTES
  • DKIM_STAT_INVALID can be returned if, for example, a signing handle using SHA256 is requested when the library was not compiled against a version of OpenSSL that had support for that hash algorithm.
RETURN VALUES
  • On success, a pointer to the created DKIM handle is returned.
  • On failure, NULL is returned and the value of statp is updated to indicate the cause of the problem.

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2011, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_signhdrs.html000066400000000000000000000040441337314105200254170ustar00rootroot00000000000000 dkim_signhdrs()

dkim_signhdrs()

[back to index]

SYNOPSIS
#include <dkim.h>

void dkim_signhdrs(
	DKIM *dkim,
        const char **hdrlist
);
Select header fields to be signed for this message, overriding the library default.
DESCRIPTION
Called When dkim_signhdrs() can be called after a signing handle is created with dkim_sign().
ARGUMENTS
ArgumentDescription
dkim A message signing handle.
hdrlist A NULL-terminated array of strings containing the names of header fields to be included in the hashes that generate this signature.
NOTES
  • This overides the list of header field names previously selected as the library default by a call to dkim_options(). It affects only the handle passed to the function. If not called, the default set configured for this library instance is used.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2013, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_ssl_version.html000066400000000000000000000032211337314105200261400ustar00rootroot00000000000000 dkim_ssl_version()

dkim_ssl_version()

[back to index]

SYNOPSIS
#include <dkim.h>
unsigned long dkim_ssl_version(void);
Retrieve the SSL version number against which the library was compiled.
DESCRIPTION
Called When dkim_ssl_version() can be called at any time.
ARGUMENTS None.
RETURN VALUES The constant OPENSSL_VERSION_NUMBER as defined by the OpenSSL package.
NOTES
  • The value returned by this function has no meaning to the library. The intent here is to confirm that the library and applications using it were both compiled with compatible versions of OpenSSL.

Copyright (c) 2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_stat.html000066400000000000000000000113731337314105200245540ustar00rootroot00000000000000 DKIM_STAT

DKIM_STAT

[back to index]

DESCRIPTION
Purpose A DKIM_STAT is a return value from libopendkim functions, either as a direct return value or a returned parameter.
Possible Values
  • DKIM_STAT_OK -- successful completion
  • DKIM_STAT_BADSIG -- at least one signature was present, but no signature successfully verified
  • DKIM_STAT_NOSIG -- no signature present
  • DKIM_STAT_NOKEY -- no key available for verifying
  • DKIM_STAT_CANTVRFY -- can't get key for verifying (e.g., DNS error)
  • DKIM_STAT_SYNTAX -- syntax error in message or signature
  • DKIM_STAT_NORESOURCE -- resource unavailable
  • DKIM_STAT_INTERNAL -- internal error
  • DKIM_STAT_REVOKED -- signing key revoked
  • DKIM_STAT_INVALID -- invalid parameter(s)
  • DKIM_STAT_NOTIMPLEMENT -- function not implemented
  • DKIM_STAT_KEYFAIL -- key retrieval failed (try again later)
  • DKIM_STAT_CBINVALID -- callback reported invalid input
  • DKIM_STAT_CBREJECT -- callback requested message rejection
  • DKIM_STAT_CBTRYAGAIN -- callback can't complete (try again later)
  • DKIM_STAT_CBERROR -- unspecified callback error
NOTES
  • DKIM_STAT_NOKEY is returned if the DNS query for a selector (public key) record returned with NXDOMAIN, i.e. the record does not exist; this should be considered a permanent failure.
  • DKIM_STAT_CANTVRFY is returned if the DNS query for a selector (public key) record timed out or suffered some other kind of transient failure; verification can be re-attempted later.
  • DKIM_STAT_SYNTAX is returned to indicate required data could not be extracted from the arriving message to be signed or verified, or if a selector (public key) record returned from a DNS query could not be parsed (e.g. corrupted, wrong format, etc.).
  • DKIM_STAT_NOSIG can be returned early, i.e. from dkim_eoh(), if no signature was found on a message which is being verified. See that function's description for further details.
  • DKIM_STAT_INTERNAL can be returned on system error (e.g. malloc() failure), or if functions provided by this API are called in the incorrect order (e.g. dkim_getsighdr() before dkim_eom(), or dkim_header() after dkim_eoh(), etc.).
  • DKIM_STAT_REVOKED is returned when a key found in a signature has been revoked and thus is no longer valid.
  • DKIM_STAT_INVALID is returned when a function in this library is called with at least one invalid parameter.
  • DKIM_STAT_NOTIMPLEMENT is returned when an attempt is made to use a feature that is not yet implemented.
  • DKIM_STAT_KEYFAIL is returned when a key retrieval operation failed for some transient reason; the caller should try again later
  • DKIM_STAT_CBINVALID is returned when a library function used a user-provided callback function which returned DKIM_CBSTAT_INVALID, indicating invalid input
  • DKIM_STAT_CBREJECT is returned when a library function used a user-provided callback function which returned DKIM_CBSTAT_REJECT, explicitly requesting message rejection
  • DKIM_STAT_CBTRYAGAIN is returned when a library function used a user-provided callback function which returned DKIM_CBSTAT_TRYAGAIN, which indicates the callback could not complete now but might work later
  • DKIM_STAT_CBERROR is returned when a library function used a user-provided callback function which returned DKIM_CBSTAT_ERROR, which indicates the callback failed

Copyright (c) 2005-2007 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, 2013, 2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dkim_verify.html000066400000000000000000000054711337314105200251070ustar00rootroot00000000000000 dkim_verify()

dkim_verify()

[back to index]

SYNOPSIS
#include <dkim.h>
DKIM *dkim_verify(
	DKIM_LIB *libhandle,
	const char *id,
	void *memclosure,
	DKIM_STAT *statp
);
Create a new handle for verifying a (possibly) signed message.
DESCRIPTION
Called When dkim_verify() is called when preparing to process a new message that may be signed already in order to be able to verify its contents against the signature.
ARGUMENTS
ArgumentDescription
libhandle DKIM library instance handle, returned by an earlier call to dkim_init().
id An opaque, printable string for identifying this message, suitable for use in logging or debug output.
memclosure Opaque memory closure, passed directly to the caller-provided malloc() and/or free() replacement functions.
statp Pointer to a DKIM_STAT object which receives the completion status of this operation.
NOTES
  • The handle returned by this function may not be used in a later call to dkim_getsighdr().
RETURN VALUES
  • On success, a pointer to the created DKIM handle is returned.
  • On failure, NULL is returned and the value of statp is updated to indicate the cause of the problem.

Copyright (c) 2005 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/dns.html000066400000000000000000000166041337314105200233630ustar00rootroot00000000000000 DNS Callback Overview

DNS Callback Overview

[back to index]

By default, libopendkim will use the standard UNIX resolver for retrieving keys and policies that are stored in the DNS. Where an application has some need for use of a resolver other than the standard one, a mechanism is provided for instructing the library to make use of that other package. This is done by using registration functions to pass pointers to the application-provided package to act as primitives for asking questions and getting answers.

The four functions provided are as follows:

  1. dkim_dns_set_query_service() -- Provides libopendkim with a handle representing the DNS resolver package to be used, such as a handle to an instantiation of a library
  2. dkim_dns_set_query_start() -- Provides libopendkim with a function that it should call when it wishes to make a request of the DNS. This function should expect to receive from libopendkim the handle provided above, the name and type to be requested from the DNS, a buffer into which to write the answer once it arrives and the length of that buffer. The function should return zero on success or non-zero on failure, and will also return (via reference) a pointer to a handle that represents the initiated query so that it can be passed to other functions. This function is responsible for establishing whatever state it will need to satisfy the other functions' requirements and provide a pointer to that state, including whatever synchronization mechanism is desired. See the page link for this function to view the actual function prototype.
  3. dkim_dns_set_query_cancel() -- Provides libopendkim with a function that it should call when it wishes to cancel a request of the DNS previously initiated by the previous function. This function should expect to receive from libopendkim the service handle provided above and the handle that represents the query to be canceled. This function will be called for all queries exactly once, including completed queries, to give the libraries a chance to deallocate memory. See the page link for this function to view the actual function prototype.
  4. dkim_dns_set_query_waitreply() -- Provides libopendkim with a function that it should call when it wishes to check for or wait on a reply to a previously initiated DNS query. This function should expect to receive from libopendkim the service handle provided above, the handle that represents the query of interest, an optional timeout via a pointer to a struct timeval, an optional pointer to a size_t that will receive the number of bytes returned, an optional pointer to an int to receive any error code, and an optional pointer to an int to receive a DKIM_DNSSEC constant if the resolver package supports such queries. The function should return a value as follows:
    • If an answer is available, the provided function should populate the optional values and the buffer provided when the query was initiated, and return the constant DKIM_DNS_SUCCESS.
    • If not, and no timeout is provided, it should wait indefinitely for an answer, returning DKIM_DNS_SUCCESS and populating values and the buffer once an answer arrives. The implementation of this waiting/wakeup mechanism is unspecified.
    • If a timeout is provided and no reply arrives in that time, the function should return DKIM_DNS_NOREPLY. If a reply does arrive in that time, it should populate the values and buffer and return DKIM_DNS_SUCCESS,
    • In case of any transport or other permanent error in resolving the request, the function should return DKIM_DNS_ERROR.
    • If the resolver decides it will no longer wait for the reply even if the application asks, it should return DKIM_DNS_EXPIRED.
    See the page link for this function to view the actual function prototype.

For the purposes of illustration, libopendkim includes a set of the above as defaults that point to the standard UNIX resolver. They are:

  1. The service handle pointer is NULL.
  2. The query start function passes the query to res_query() and then creates a small state handle that stores the return value from that function, which is the length of the reply. res_query() populates the buffer provided, and doesn't return until it completes (i.e. it is synchronous) so in fact a final result is already available. It returns 0, unless res_query() returns an error in which case it returns -1.
  3. The query cancel function deallocates the state handle. It always returns 0.
  4. The query waitreply function copies the reply length and error code from the state handle to the provided integer pointers and returns DKIM_DNS_SUCCESS immediately.

So from libopendkim's perspective, it starts a query and then asks for a reply, but the reply has actually already completed so the wait stage is almost a no-op except to get the length of the reply.

Looking at a slightly more complicated case, we consider how it would work with libar:

  1. The service handle pointer is the return value from ar_init(), which creates an instance of the libar service.
  2. The query start function passes the query to ar_addquery() and returns the query handle generated by that function.
  3. The query cancel function merely passes the service handle and the query handle to ar_cancelquery().
  4. The query wait function passes the service and query handles to ar_waitreply() with whatever the requested timeout was. On return it copies the returned number of bytes to the caller, or any appropriate error code. If waiting is required, this is implemented inside ar_waitreply() using POSIX condition variables.

In this case, operation is fairly straightforward until the wait operation. If libar has a reply available, the wait function above would get AR_STAT_SUCCESS back immediately, and can thus return DKIM_DNS_SUCCESS to libopendkim immediately. If the reply is still pending, libopendkim will get DKIM_DNS_NOREPLY back and can do other work while libar is still waiting. If libopendkim wishes to wait, the timeout it provides is turned into a POSIX condition wait and the libar dispatcher thread will signal it when a reply arrives.



Copyright (c) 2010, 2011, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/index.html000066400000000000000000000516201337314105200237030ustar00rootroot00000000000000 OpenDKIM Library (libopendkim)

OpenDKIM Library (libopendkim)

Introduction

DomainKeys Identified Mail ("DKIM") is a specification for signing messages at the domain level using simple cryptographic methods to indicate that the signing domain accepts some responsibility for the message. While the most obvious application of this is to defend against forged mail, other applications can make use of this capability.

DKIM is an amalgamation of DomainKeys, created by Yahoo!, Inc., and Internet Identified Mail (IIM) created by Cisco, Inc. Both can be found as historical RFCs documents via the IETF web sites. More information about DomainKeys can be found here.

This API (libopendkim) allows an application to sign or verify messages according to the DKIM proposed standard. It also includes a number of extensions to support other protocols that are not part of DKIM itself. Support is included for ADSP, a mechanism for determining whether or not the purported author domain claims all of its mail is signed. Also provided is an implementation of a filter, using Sendmail's milter package, that uses libopendkim to implement this facility.

Data Types

Data Type Description
DKIM A signing/verifying context for a message.
dkim_alg_t A signature generation/verification method.
dkim_atps_t An Authorized Third-Party Signer test result.
dkim_canon_t A canonicalization method.
DKIM_CBSTAT Return value/status from user-provided callbacks.
DKIM_DNSSEC Key record security evaluation codes.
DKIM_LIB An instance of the libopendkim service.
dkim_param_t A signature parameter.
dkim_query_t A key query method.
DKIM_QUERYINFO A handle describing a required DNS query.
DKIM_SIGERROR Signature evaluation error codes.
DKIM_SIGINFO Private handle referencing information about a particular signature on a signed message.
dkim_sigkey_t Private key data.
DKIM_STAT Return value/status.

Functions

Function Description
Administration
dkim_init() Initialize an instance of the DKIM service.
dkim_flush_cache() Flush the key cache.
dkim_getcachestats() Retrieve caching statistics.
dkim_geterror() Retrieve the most recent internal error message associated with a DKIM handle.
dkim_getmode() Return the mode (signing or verifying) of a DKIM handle.
dkim_get_signer() Retrieve the current message signer (if any).
dkim_get_user_context() Retrieve a specific user context pointer for a sign or verify operation previously set by a call to dkim_set_user_context().
dkim_libfeature() Test for availability of a particular feature in the library.
dkim_libversion() Retrieve the version of libopendkim against which the application is linked.
dkim_set_dns_callback() Request a call back into the main program from time to time while waiting for DNS results.
dkim_set_final() Provide a function to perform final signature analysis and/or re-ordering during verifications.
dkim_set_key_lookup() Provide a function to perform key lookups, replacing the internal implementation. Includes support for asynchronous operation.
dkim_set_prescreen() Provide a function to perform signature prescreening and/or re-ordering during verifications.
dkim_set_signature_handle() Provide a function to allocate a user-side signature description structure and return a pointer to it.
dkim_set_signature_handle_free() Provide a function to deallocate a user-side signature description structure.
dkim_set_signature_tagvalues() Provide a function to receive signature-specific tags and values for user-side analysis.
dkim_set_user_context() Set a specific user context pointer for a sign or verify operation which will be passed to user callbacks.
dkim_ssl_version() Retrieve the OpenSSL version used when the library was compiled.
dkim_close() Terminate an instance of the DKIM service.
Signing
dkim_sign() Allocate a new DKIM handle for signing a message.
dkim_add_querymethod() Indicate to verifiers which signing method(s) and option(s) should be used to retrieve the public key for verification.
dkim_add_xtag() Add an extension tag and corresponding value.
dkim_getpartial() Check partial signature request flag.
dkim_getsighdr() Generate and return a signature header into a fixed-size buffer.
dkim_getsighdr_d() Generate and return a signature header in a dynamically-allocated buffer.
dkim_privkey_load() Attempt to parse and load a signing key.
dkim_set_margin() Set the wrapping margin to use for signature header generation.
dkim_set_signer() Set the message signer.
dkim_setpartial() Request "l=" tag on a signature.
dkim_signhdrs() Select header fields to be signed for this message, overriding the default.
Verifying
dkim_verify() Allocate a new DKIM handle for verifying a message.
dkim_atps_check() Perform an Authorized Third-Party Signer check.
dkim_diffheaders() Compare original headers to received headers and look for approximate matches to identify header munging in order to explain verification failures.
dkim_get_reputation() Query a DKIM reputation service.
dkim_getdomain() Return the sending domain from a message represented by a DKIM handle.
dkim_getresultstr() Translate a DKIM_STAT constant into a string.
dkim_getsiglist() Retrieve the array of signature handles associated with a message.
dkim_getsignature() Retrieve the signature handle to be used for final message disposition.
dkim_getsslbuf() Retrieve the SSL error buffer for a DKIM signing handle.
dkim_getuser() Return the sending user from a message represented by a DKIM handle.
dkim_minbody() Return number of bytes required to satisfy all active canonicalizations referenced by a DKIM handle.
dkim_ohdrs() Retrieve the original header set from a signature if such were present.
dkim_sig_getbh() Retrieve body hash test result from a signature handle.
dkim_sig_getcanonlen() Retrieve information regarding total canonicalized body length, and the size of what was actually signed.
dkim_sig_getcanons() Retrieve the canonicalization modes used to generate a signature.
dkim_sig_getcontext() Retrieve user-side context specific to a signature.
dkim_sig_getdnssec() Retrieve DNSSEC evaluation of a signature's key record.
dkim_sig_getdomain() Retrieve the domain name found in the signature on a message.
dkim_sig_geterror() Retrieve the error code associated with a rejected/disqualified signature.
dkim_sig_geterrorstr() Retrieve the text version of a signature error code.
dkim_sig_getflags() Retrieve processing flags from a signature handle.
dkim_sig_getidentity() Retrieve the identity of the signing agent from a signature or message.
dkim_sig_getkeysize() Retrieve the size in bits of the key used to verify a message.
dkim_sig_getqueries() Get the set of DNS queries needed to complete signature validation.
dkim_sig_getreportinfo() Retrieve information required to generate a verification failure report.
dkim_sig_getselector() Retrieve the selector found in a signature on a message.
dkim_sig_getsignalg() Retrieve the signature algorithm used to sign a message.
dkim_sig_getsignedhdrs() Retrieve signed header data.
dkim_sig_getsigntime() Retrieve the timestamp on the signature of a message.
dkim_sig_getsslbuf() Retrieve the SSL error buffer for a signature.
dkim_sig_hdrsigned() Determine whether or not a particular header was signed.
dkim_sig_ignore() Flag a signature to be ignored when verifying.
dkim_sig_process() Process a signature for validity.
dkim_sig_setdnssec() Set the DNSSEC result code associated with a signature.
dkim_sig_seterror() Set the error code associated with a signature.
Processing
dkim_header() Process a header.
dkim_eoh() Identify end of headers.
dkim_body() Process a body chunk.
dkim_eom() Identify end of message.
dkim_chunk() Process a message chunk.
Utility
dkim_getid() Retrieve "id" string from handle.
dkim_get_msgdate() Attempt to parse the Date: header field of a message and return its UNIX time_t conversion as a 64-bit unsigned integer.
dkim_get_sigsubstring() Retrieve a minimal signature substring for matching results to signatures.
dkim_key_syntax() Check the syntax of a key record.
dkim_mail_parse() Parse a message header field, e.g. From:, to get user and domain.
dkim_mail_parse_multi() Parse a message header field, e.g. To: or Cc:, to get users and domains.
dkim_options() Get or set library options.
dkim_qi_getname() Retrieve the DNS name from a DKIM_QUERYINFO handle.
dkim_qi_gettype() Retrieve the DNS resource record type from a DKIM_QUERYINFO handle.
dkim_sig_gethashes() Retrieve computed hashes related to a signature.
dkim_sig_gettagvalue() Retrieve arbitrary tags and values from signatures and keys.
dkim_sig_syntax() Check the syntax of a signature.
DNS Operations
dkim_dns_close() Force shutdown of the DNS resolver in use by the library.
dkim_dns_config() Provide the active DNS resolver with arbitrary configuration information to be used.
dkim_dns_init() Force initialization of the DNS resolver to be used by the library.
dkim_dns_nslist() Provide the active DNS resolver with a new set of nameservers to be used.
dkim_dns_set_close() Set the function to be used by the library to terminate a DNS resolver.
dkim_dns_set_config() Set the function to be used by the library to pass arbitrary configuration data to the underlying resolver.
dkim_dns_set_init() Set the function to be used by the library to initialize a DNS resolver.
dkim_dns_set_nslist() Set the function to be used by the library to change the set of nameservers in use by a DNS resolver.
dkim_dns_set_query_cancel() Set the function to be used by the library to cancel a pending DNS query whose result is no longer needed.
dkim_dns_set_query_service() Set the DNS query service handle to be used by the library.
dkim_dns_set_query_start() Set the DNS query start function to be used by the library.
dkim_dns_set_query_waitreply() Set the function to be used by the library to wait for a reply to a pending DNS query.
dkim_dns_set_trustanchor() Set the function to be used by the library to pass arbitrary trust anchor data to the underlying resolver.
dkim_dns_trustanchor() Provide the active DNS resolver with trust anchor configuration information to be used.
Cleanup
dkim_free() Destroy a per-message handle of the DKIM service.

An overview of the general use of this API is available here. An overview of the DNS resolver portion of the API is available here.
Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/docs/overview.html000066400000000000000000000136011337314105200244370ustar00rootroot00000000000000 Overview

Overview

[back to index]

To sign a message under DomainKeys Identified Mail ("DKIM"), make the following calls:
  1. lib = dkim_init(...);
    • initialize an instance of the library
    • this must be done once before any of the other calls are made
    • this needs to be called once when the application is started, but its result can be reused at the start of processing of each message
    • the remaining steps can use the same value of lib, even in multiple threads and over multiple messages
  2. dkim = dkim_sign(lib, ...);
    • initialize a handle set up for signing the message
    • at this point a canonicalization, signing algorithm and secret key are selected by the caller
  3. stat = dkim_header(dkim, ...);
    • pass a header field to libopendkim
    • this should be done once for each header field that should be included in computation of the signature
  4. stat = dkim_eoh(dkim);
    • notify libopendkim that the end of this message's header has been reached
  5. stat = dkim_body(dkim, ...);
    • pass to libopendkim a chunk of the body that should be included in computation of the signature (currently all of it)
    • repeat for each body chunk that arrives
  6. stat = dkim_eom(dkim);
    • notify libopendkim that the end of this message has been reached
  7. stat = dkim_getsighdr(dkim, ...);
    • compute the base64-encoded signature for the message
    • the signing algorithm was selected in the call to dkim_sign() above
    • the entire signature header field is generated and returned into a buffer provided by the caller, so it can be added to the message
  8. stat = dkim_free(dkim);
    • free resources related to this message
  9. dkim_close(lib);
    • free resources related to this library instance

To verify a message under DKIM, make the following calls:
  1. lib = dkim_init(...);
    • initialize an instance of the library
    • this must be done once before any of the other calls are made
    • this needs to be called once when the application is started, but its result can be reused at the start of processing of each message
    • the remaining steps can use the same value of lib, even in multiple threads and over multiple messages
  2. dkim = dkim_verify(lib, ...);
    • initialize a handle set up for verifying the message
    • the canonicalization and signing algorithms and public key were selected by the agent that signed the message, and so don't need to be provided here
  3. stat = dkim_header(dkim, ...);
    • pass a header field to libopendkim
    • this should be done once for each header field that should be included in computation of the digest to be verified (currently all of them)
  4. stat = dkim_eoh(dkim);
    • notify libopendkim that the end of this message's header has been reached
  5. stat = dkim_body(dkim, ...);
    • pass to libopendkim a chunk of the body that should be included in computation of the digest to be verified (currently all of it)
  6. stat = dkim_eom(dkim);
    • notify libopendkim that the end of this message has been reached
    • see if stat is DKIM_STAT_OK (verification OK) or DKIM_STAT_BADSIG (verification failed)
  7. stat = dkim_free(dkim);
    • free resources related to this message
  8. dkim_close(lib);
    • free resources related to this library instance

One application, having called dkim_init() once, can call dkim_sign() or dkim_verify() more than once each, and furthermore can have more than one signing/verifying handle in existence at any given time.

Note that new dkim_chunk() interface can replace the dkim_header()-dkim_eoh()-dkim_body() sequence for applications that don't have the header fields individually separated.

One can also use new dkim_getsighdr_d() in place of dkim_getsighdr() to allow larger-than-normal signatures to be generated.


Copyright (c) 2005, 2007, 2008 Sendmail, Inc. and its suppliers. All rights reserved.
Copyright (c) 2009, 2010, The Trusted Domain Project. All rights reserved.
By using this file, you agree to the terms and conditions set forth in the respective licenses.
OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/opendkim.pc.in000066400000000000000000000006671337314105200235220ustar00rootroot00000000000000# Process this file with autoconf to produce a pkg-config metadata file. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@/opendkim Name: OpenDKIM Library Description: Library for performing DKIM signing and verification URL: http://opendkim.org Version: @VERSION@ Libs: -L${libdir} @PTHREAD_CFLAGS@ -lopendkim Libs.private: @LIBOPENDKIM_LIBS_PKG@ @PTHREAD_LIBS@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/000077500000000000000000000000001337314105200221145ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/.gitignore000066400000000000000000000007071337314105200241100ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno *.gmon *.prof *.info *.gcov t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ .info-files autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure configure.scan aclocal.m4 description.html description.txt depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile symbols.map .libs .deps core *.core gmon.out OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/Makefile.am000066400000000000000000000273501337314105200241570ustar00rootroot00000000000000 AM_CFLAGS = $(COV_CFLAGS) AM_LDFLAGS = $(COV_LDFLAGS) if DEBUG AM_CFLAGS += -g endif LDADD = ../libopendkim.la $(COV_LIBADD) $(LIBCRYPTO_LIBS) $(LIBRESOLV) AM_CPPFLAGS = -I.. if USE_GNUTLS AM_CFLAGS += $(LIBCRYPTO_CFLAGS) AM_CPPFLAGS += $(LIBCRYPTO_CPPFLAGS) AM_LDFLAGS += $(LIBCRYPTO_LDFLAGS) endif PROF_SRCS = base64.c dkim-cache.c dkim-canon.c dkim-keys.c dkim-mailparse.c dkim-policy.c dkim-rep.c dkim-strl.c dkim-tables.c dkim-test.c dkim-ub.c dkim-util.c dkim.c util.c check_PROGRAMS = t-setup t-test00 t-test01 t-test02 t-test03 t-test04 \ t-test05 t-test06 t-test07 t-test08 t-test09 t-test10 t-test11 \ t-test12 t-test13 t-test14 t-test15 t-test16 t-test17 t-test18 \ t-test19 t-test20 t-test21 t-test22 t-test23 t-test24 t-test25 \ t-test26 t-test27 t-test28 t-test29 t-test30 t-test31 t-test32 \ t-test33 t-test34 t-test35 t-test36 t-test37 t-test38 t-test39 \ t-test40 t-test41 t-test42 t-test43 t-test44 t-test45 t-test46 \ t-test47 t-test48 t-test50 t-test51 t-test52 t-test53 \ t-test54 t-test55 t-test56 t-test57 t-test58 t-test59 t-test60 \ t-test61 t-test62 t-test63 t-test64 t-test65 t-test66 t-test67 \ t-test68 t-test69 t-test70 t-test71 t-test72 t-test73 t-test74 \ t-test76 t-test77 t-test78 t-test79 t-test80 t-test81 \ t-test82 t-test83 t-test84 t-test85 t-test86 t-test87 t-test88 \ t-test89 t-test90 t-test91 t-test92 t-test93 t-test94 t-test95 \ t-test96 t-test97 t-test98 t-test99 t-test100 t-test101 t-test102 \ t-test103 t-test104 t-test105 t-test106 t-test107 t-test108 \ t-test109 t-test110 t-test111 t-test112 t-test114 \ t-test115 t-test116 t-test117 t-test119 t-test120 \ t-test121 t-test122 t-test123 t-test125 t-test126 \ t-test127 t-test128 t-test129 t-test130 t-test131 t-test132 \ t-test133 t-test134 t-test135 t-test136 t-test137 t-test138 \ t-test139 t-test140 t-test141 t-test142 t-test143 t-test144 \ t-test145 t-test146 t-test147 t-test148 t-test149 t-test150 \ t-test151 t-test152 t-test153 t-test154 t-test155 t-test156 \ t-test157 t-test158 \ t-signperf t-verifyperf check_SCRIPTS = t-signperf-sha1 t-signperf-relaxed-relaxed \ t-signperf-simple-simple if ALL_SYMBOLS check_PROGRAMS += t-test49 t-test113 t-test118 endif check_PROGRAMS += t-cleanup TESTS = $(check_PROGRAMS) $(check_SCRIPTS) EXTRA_DIST = $(check_SCRIPTS) t_setup_SOURCES = t-setup.c t-testdata.h t_cleanup_SOURCES = t-cleanup.c t-testdata.h t_signperf_SOURCES = t-signperf.c t-testdata.h t_verifyperf_SOURCES = t-verifyperf.c t-testdata.h t_test00_SOURCES = t-test00.c t-testdata.h t_test01_SOURCES = t-test01.c t-testdata.h t_test02_SOURCES = t-test02.c t-testdata.h t_test03_SOURCES = t-test03.c t-testdata.h t_test04_SOURCES = t-test04.c t-testdata.h t_test05_SOURCES = t-test05.c t-testdata.h t_test06_SOURCES = t-test06.c t-testdata.h t_test07_SOURCES = t-test07.c t-testdata.h t_test08_SOURCES = t-test08.c t-testdata.h t_test09_SOURCES = t-test09.c t-testdata.h t_test10_SOURCES = t-test10.c t-testdata.h t_test11_SOURCES = t-test11.c t-testdata.h t_test12_SOURCES = t-test12.c t-testdata.h t_test13_SOURCES = t-test13.c t-testdata.h t_test14_SOURCES = t-test14.c t-testdata.h t_test15_SOURCES = t-test15.c t-testdata.h t_test16_SOURCES = t-test16.c t-testdata.h t_test17_SOURCES = t-test17.c t-testdata.h t_test18_SOURCES = t-test18.c t-testdata.h t_test19_SOURCES = t-test19.c t-testdata.h t_test20_SOURCES = t-test20.c t-testdata.h t_test21_SOURCES = t-test21.c t-testdata.h t_test22_SOURCES = t-test22.c t-testdata.h t_test23_SOURCES = t-test23.c t-testdata.h t_test24_SOURCES = t-test24.c t-testdata.h t_test25_SOURCES = t-test25.c t-testdata.h t_test26_SOURCES = t-test26.c t-testdata.h t_test27_SOURCES = t-test27.c t-testdata.h t_test28_SOURCES = t-test28.c t-testdata.h t_test29_SOURCES = t-test29.c t-testdata.h t_test30_SOURCES = t-test30.c t-testdata.h t_test31_SOURCES = t-test31.c t-testdata.h t_test32_SOURCES = t-test32.c t-testdata.h t_test33_SOURCES = t-test33.c t-testdata.h t_test34_SOURCES = t-test34.c t-testdata.h t_test35_SOURCES = t-test35.c t-testdata.h t_test36_SOURCES = t-test36.c t-testdata.h t_test37_SOURCES = t-test37.c t-testdata.h t_test38_SOURCES = t-test38.c t-testdata.h t_test39_SOURCES = t-test39.c t-testdata.h t_test40_SOURCES = t-test40.c t-testdata.h t_test41_SOURCES = t-test41.c t-testdata.h t_test42_SOURCES = t-test42.c t-testdata.h t_test43_SOURCES = t-test43.c t-testdata.h t_test44_SOURCES = t-test44.c t-testdata.h t_test45_SOURCES = t-test45.c t-testdata.h t_test46_SOURCES = t-test46.c t-testdata.h t_test47_SOURCES = t-test47.c t-testdata.h t_test48_SOURCES = t-test48.c t-testdata.h t_test49_SOURCES = t-test49.c t-testdata.h t_test50_SOURCES = t-test50.c t-testdata.h t_test51_SOURCES = t-test51.c t-testdata.h t_test52_SOURCES = t-test52.c t-testdata.h t_test53_SOURCES = t-test53.c t-testdata.h t_test54_SOURCES = t-test54.c t-testdata.h t_test55_SOURCES = t-test55.c t-testdata.h t_test56_SOURCES = t-test56.c t-testdata.h t_test57_SOURCES = t-test57.c t-testdata.h t_test58_SOURCES = t-test58.c t-testdata.h t_test59_SOURCES = t-test59.c t-testdata.h t_test60_SOURCES = t-test60.c t-testdata.h t_test61_SOURCES = t-test61.c t-testdata.h t_test62_SOURCES = t-test62.c t-testdata.h t_test63_SOURCES = t-test63.c t-testdata.h t_test64_SOURCES = t-test64.c t-testdata.h t_test65_SOURCES = t-test65.c t-testdata.h t_test66_SOURCES = t-test66.c t-testdata.h t_test67_SOURCES = t-test67.c t-testdata.h t_test68_SOURCES = t-test68.c t-testdata.h t_test69_SOURCES = t-test69.c t-testdata.h t_test70_SOURCES = t-test70.c t-testdata.h t_test71_SOURCES = t-test71.c t-testdata.h t_test72_SOURCES = t-test72.c t-testdata.h t_test73_SOURCES = t-test73.c t-testdata.h t_test74_SOURCES = t-test74.c t-testdata.h t_test76_SOURCES = t-test76.c t-testdata.h t_test77_SOURCES = t-test77.c t-testdata.h t_test78_SOURCES = t-test78.c t-testdata.h t_test79_SOURCES = t-test79.c t-testdata.h t_test80_SOURCES = t-test80.c t-testdata.h t_test81_SOURCES = t-test81.c t-testdata.h t_test82_SOURCES = t-test82.c t-testdata.h t_test83_SOURCES = t-test83.c t-testdata.h t_test84_SOURCES = t-test84.c t-testdata.h t_test85_SOURCES = t-test85.c t-testdata.h t_test86_SOURCES = t-test86.c t-testdata.h t_test87_SOURCES = t-test87.c t-testdata.h t_test88_SOURCES = t-test88.c t-testdata.h t_test89_SOURCES = t-test89.c t-testdata.h t_test90_SOURCES = t-test90.c t-testdata.h t_test91_SOURCES = t-test91.c t-testdata.h t_test92_SOURCES = t-test92.c t-testdata.h t_test93_SOURCES = t-test93.c t-testdata.h t_test94_SOURCES = t-test94.c t-testdata.h t_test95_SOURCES = t-test95.c t-testdata.h t_test96_SOURCES = t-test96.c t-testdata.h t_test97_SOURCES = t-test97.c t-testdata.h t_test98_SOURCES = t-test98.c t-testdata.h t_test99_SOURCES = t-test99.c t-testdata.h t_test100_SOURCES = t-test100.c t-testdata.h t_test101_SOURCES = t-test101.c t-testdata.h t_test102_SOURCES = t-test102.c t-testdata.h t_test103_SOURCES = t-test103.c t-testdata.h t_test104_SOURCES = t-test104.c t-testdata.h t_test105_SOURCES = t-test105.c t-testdata.h t_test106_SOURCES = t-test106.c t-testdata.h t_test107_SOURCES = t-test107.c t-testdata.h t_test108_SOURCES = t-test108.c t-testdata.h t_test109_SOURCES = t-test109.c t-testdata.h t_test110_SOURCES = t-test110.c t-testdata.h t_test111_SOURCES = t-test111.c t-testdata.h t_test112_SOURCES = t-test112.c t-testdata.h if ALL_SYMBOLS t_test113_SOURCES = t-test113.c t-testdata.h endif t_test114_SOURCES = t-test114.c t-testdata.h t_test115_SOURCES = t-test115.c t-testdata.h t_test116_SOURCES = t-test116.c t-testdata.h t_test117_SOURCES = t-test117.c t-testdata.h if ALL_SYMBOLS t_test118_SOURCES = t-test118.c t-testdata.h endif t_test119_SOURCES = t-test119.c t-testdata.h t_test120_SOURCES = t-test120.c t-testdata.h t_test121_SOURCES = t-test121.c t-testdata.h t_test122_SOURCES = t-test122.c t-testdata.h t_test123_SOURCES = t-test123.c t-testdata.h t_test125_SOURCES = t-test125.c t-testdata.h t_test126_SOURCES = t-test126.c t-testdata.h t_test127_SOURCES = t-test127.c t-testdata.h t_test128_SOURCES = t-test128.c t-testdata.h t_test129_SOURCES = t-test129.c t-testdata.h t_test130_SOURCES = t-test130.c t-testdata.h t_test131_SOURCES = t-test131.c t-testdata.h t_test132_SOURCES = t-test132.c t-testdata.h t_test133_SOURCES = t-test133.c t-testdata.h t_test134_SOURCES = t-test134.c t-testdata.h t_test135_SOURCES = t-test135.c t-testdata.h t_test136_SOURCES = t-test136.c t-testdata.h t_test137_SOURCES = t-test137.c t-testdata.h t_test138_SOURCES = t-test138.c t-testdata.h t_test139_SOURCES = t-test139.c t-testdata.h t_test140_SOURCES = t-test140.c t-testdata.h t_test141_SOURCES = t-test141.c t-testdata.h t_test142_SOURCES = t-test142.c t-testdata.h t_test143_SOURCES = t-test143.c t-testdata.h t_test144_SOURCES = t-test144.c t-testdata.h t_test145_SOURCES = t-test145.c t-testdata.h t_test146_SOURCES = t-test146.c t-testdata.h t_test147_SOURCES = t-test147.c t-testdata.h t_test148_SOURCES = t-test148.c t-testdata.h t_test149_SOURCES = t-test149.c t-testdata.h t_test150_SOURCES = t-test150.c t-testdata.h t_test151_SOURCES = t-test151.c t-testdata.h t_test152_SOURCES = t-test152.c t-testdata.h t_test153_SOURCES = t-test153.c t-testdata.h t_test154_SOURCES = t-test154.c t-testdata.h t_test155_SOURCES = t-test155.c t-testdata.h t_test156_SOURCES = t-test156.c t-testdata.h t_test157_SOURCES = t-test157.c t-testdata.h MOSTLYCLEANFILES= if GCOV_ONLY MOSTLYCLEANFILES+=*.gcov *.gcno *.gcda *.bb *.bbg *.da .gcov-files #TESTS_ENVIRONMENT=./gcov-helper.sh #.gcov-files: check-TESTS # for i in $(PROF_SRCS); do \ # x=`echo $$i | sed 's/\..*//g'`; \ # if test -f ../libopendkim_la-$$x.gcno -a \ # -f ../libopendkim_la-$$x.gcda; then \ # mv ../libopendkim_la-$$x.gcno ../$$x.gcno; \ # mv ../libopendkim_la-$$x.gcda ../$$x.gcda; \ # gcov -o .. $$i; \ # fi; \ # if test -f ../libopendkim_la-$$x.bb -a \ # -f ../libopendkim_la-$$x.bbg -a \ # -f ../libopendkim_la-$$x.da; then \ # mv ../libopendkim_la-$$x.bb ../$$x.bb; \ # mv ../libopendkim_la-$$x.bbg ../$$x.bbg; \ # mv ../libopendkim_la-$$x.da ../$$x.da; \ # gcov -o .. $$i; \ # fi; \ # done # touch $@ # #check-local: .gcov-files endif if LCOV dist_doc_DATA=lcov MAINTAINERCLEANFILES=description.txt description.html MOSTLYCLEANFILES+=*.info .prepare-lcov .info-files *.gcno *.gcda #.info-files: check-TESTS # for i in $(PROF_SRCS); do \ # x=`echo $$i | sed 's/\..*//g'`; \ # if test -f ../libopendkim_la-$$x.gcno -a \ # -f ../libopendkim_la-$$x.gcda; then \ # mv ../libopendkim_la-$$x.gcno ../$$x.gcno; \ # mv ../libopendkim_la-$$x.gcda ../$$x.gcda; \ # fi; \ # lcov --capture --directory .. --output-file $$x.info \ # --test-name $$x -q; \ # done # touch .info-files TESTS_ENVIRONMENT=./lcov-helper.sh #check-local: .info-files description.html check-local: check-TESTS description.html genhtml --output-directory lcov *.info --show-details --highlight \ --frames --legend --title libopendkim \ --description-file description.html # remove t- prefix and replace - with _ from testnames because lcov doesn't handle it # keep consistant with gcov-helper.sh description.txt: $(check_PROGRAMS) $(check_SCRIPTS) rm -f $@ for i in $(check_PROGRAMS); do \ testname=$${i/t-}; \ testname=$${testname//-/_}; \ fgrep '***' $$i.c | tail -n 1 | \ (echo $${testname} ; sed -e 's/[^*]*\*\*\*\(.*\)\\n.*/\t\1\n/g' ) >> $@; \ done for i in $(check_SCRIPTS); do \ testname=$${i/t-}; \ testname=$${testname//-/_}; \ grep '^#' $$i | tail -n 1 | \ (echo $${testname} ; sed -e 's/^# \(.*\)/\t\1\n/g' ) >> $@; \ done description.html: description.txt gendesc --output $@ $? maintainer-clean-local: -rm -rf lcov/[^CR]* .PHONY: maintainer-clean-local check-local endif if GPROF MOSTLYCLEANFILES+=*.prof gmon.out *.gmon check-local: check-TESTS if GPROF_FILENAMES for i in $(check_PROGRAMS); do \ ./$$i; \ gprof $$i $$i.gmon > $$i.prof; \ done else for i in $(check_PROGRAMS); do \ ./$$i; \ gprof $$i > $$i.prof; \ done endif endif OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/gcov-helper.sh000077500000000000000000000003551337314105200246710ustar00rootroot00000000000000#!/bin/sh $1 x=$? myname=`basename $1` if test x"$OSTYPE" = x"OpenBSD" then mv *$myname.bb $myname.bb mv *$myname.bbg $myname.bbg mv *$myname.da $myname.da else mv *$myname.gcda $myname.gcda mv *$myname.gcno $myname.gcno fi exit $x OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/lcov-helper.sh000077500000000000000000000004101337314105200246660ustar00rootroot00000000000000#!/bin/bash $1 x=$? # keep consistant with Makefile.am testname=${1/.\/t-} testname=${testname//-/_} lcov --capture --directory .. --output-file $1.info --test-name ${testname} --quiet lcov --remove $1.info '/usr/include/*' --output-file $1.info --quiet & exit $x OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/lcov/000077500000000000000000000000001337314105200230575ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/lcov/.gitignore000066400000000000000000000000061337314105200250430ustar00rootroot00000000000000[^R]* OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/lcov/README000066400000000000000000000002771337314105200237450ustar00rootroot00000000000000This directory will contain the output of an "lcov" (code coverage) report run during packaging of this release. To read it, point your favourite browser at "index.html" in this directory. OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-cleanup.c000066400000000000000000000012521337314105200241500ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "t-testdata.h" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { /* needed for code coverage test descriptions */ printf("*** test cleanup\n"); assert(unlink(KEYFILE) == 0); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-setup.c000066400000000000000000000051151337314105200236630ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { char *p; FILE *f; printf("*** test setup\n"); f = fopen(KEYFILE, "w"); assert(f != NULL); fprintf(f, "%s.%s.%s ", SELECTOR, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEY; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTOR2, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEY2; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTOR, DKIM_DNSKEYNAME, DOMAIN2); for (p = PUBLICKEYNOS; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTORBADV, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYBADV; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTOR256, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEY256; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTORBADH, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYBADH; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTORNOK, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYNOK; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTORBADK, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYBADK; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTOREMPTYP, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYEMPTYP; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTORNOP, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYNOP; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "%s.%s.%s ", SELECTORCORRUPTP, DKIM_DNSKEYNAME, DOMAIN); for (p = PUBLICKEYCORRUPTP; *p != '\0'; p++) { if (*p != '\n') putc(*p, f); } fprintf(f, "\n"); fprintf(f, "dkim=all; t=s; r=%s\n", REPLYADDRESS); fprintf(f, "%s exists\n", DOMAIN2); fclose(f); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-signperf-relaxed-relaxed000077500000000000000000000001561337314105200271660ustar00rootroot00000000000000#!/bin/sh # # # Speed signing test using relaxed/relaxed canonicalization ./t-signperf -b relaxed -h relaxed OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-signperf-sha1000077500000000000000000000001271337314105200247520ustar00rootroot00000000000000#!/bin/sh # # # Speed signing test using sha1 hash algorithm ./t-signperf -s rsa-sha1 OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-signperf-simple-simple000077500000000000000000000001521337314105200266740ustar00rootroot00000000000000#!/bin/sh # # # Speed signing test using simple/simple canonicalization ./t-signperf -b simple -h simple OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-signperf.c000066400000000000000000000155321337314105200243440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define DEFMSGSIZE 1024 #define DEFTESTINT 5 #define BODYBUFRSZ 8192 #define MAXHEADER 4096 #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ char *progname; /* ** CANON_CODE -- convert a canonicalization name to its code ** ** Parameters: ** name -- name to convert ** ** Return value: ** dkim_canon_t */ dkim_canon_t canon_code(char *name) { if (name == NULL) return (dkim_canon_t) DKIM_CANON_UNKNOWN; else if (strcasecmp(name, "simple") == 0) return (dkim_canon_t) DKIM_CANON_SIMPLE; else if (strcasecmp(name, "relaxed") == 0) return (dkim_canon_t) DKIM_CANON_RELAXED; else return (dkim_canon_t) DKIM_CANON_UNKNOWN; } /* ** CANON_NAME -- convert a canonicalization code to its name ** ** Parameters: ** code -- code to convert ** ** Return value: ** Pointer to name string. */ char * canon_name(dkim_canon_t code) { switch (code) { case DKIM_CANON_SIMPLE: return "simple"; case DKIM_CANON_RELAXED: return "relaxed"; case DKIM_CANON_UNKNOWN: default: return "unknown"; } } /* ** ALG_CODE -- convert an algorithm name to its code ** ** Parameters: ** name -- name to convert ** ** Return value: ** dkim_alg_t */ dkim_alg_t alg_code(char *name) { if (name == NULL) return (dkim_alg_t) DKIM_SIGN_UNKNOWN; else if (strcasecmp(name, "rsa-sha1") == 0) return (dkim_alg_t) DKIM_SIGN_RSASHA1; else if (strcasecmp(name, "rsa-sha256") == 0) return (dkim_alg_t) DKIM_SIGN_RSASHA256; else return (dkim_alg_t) DKIM_SIGN_UNKNOWN; } /* ** ALG_NAME -- convert an algorithm code to its name ** ** Parameters: ** code -- code to convert ** ** Return value: ** Pointer to name string. */ char * alg_name(dkim_alg_t code) { switch (code) { case DKIM_SIGN_DEFAULT: return "default"; case DKIM_SIGN_RSASHA1: return "rsa-sha1"; case DKIM_SIGN_RSASHA256: return "rsa-sha256"; case DKIM_SIGN_UNKNOWN: default: return "unknown"; } } /* ** USAGE -- print usage message ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\n" "\t-b bodycanon\tbody canonicalization to use\n" "\t-h hdrcanon \theader canonicalization to use\n" "\t-m bytes \tmessage size in bytes\n" "\t-s signalg \tsigning algorithm to use\n" "\t-t seconds \ttest time in seconds\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { DKIM_STAT status; u_int signcnt = 0; int c; int w; int rate; size_t msgsize = DEFMSGSIZE; size_t msgrem; size_t wsz; char *p; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; unsigned char body[BODYBUFRSZ]; time_t start = DEFTESTINT; time_t testint = DEFTESTINT; dkim_canon_t hcanon = DKIM_CANON_RELAXED; dkim_canon_t bcanon = DKIM_CANON_SIMPLE; dkim_alg_t signalg = DKIM_SIGN_UNKNOWN; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, "b:h:m:s:t:")) != -1) { switch (c) { case 'b': bcanon = canon_code(optarg); if (bcanon == (dkim_canon_t) -1) { fprintf(stderr, "%s: unknown canonicalization '%s'\n", progname, optarg); return EX_USAGE; } break; case 'h': hcanon = canon_code(optarg); if (hcanon == (dkim_canon_t) -1) { fprintf(stderr, "%s: unknown canonicalization '%s'\n", progname, optarg); return EX_USAGE; } break; case 'm': msgsize = strtoul(optarg, &p, 10); if (*p != '\0') { fprintf(stderr, "%s: invalid size '%s'\n", progname, optarg); return EX_USAGE; } break; case 's': signalg = alg_code(optarg); if (signalg == (dkim_alg_t) -1) { fprintf(stderr, "%s: unknown signing algorithm '%s'\n", progname, optarg); return EX_USAGE; } break; case 't': testint = strtoul(optarg, &p, 10); if (*p != '\0') { fprintf(stderr, "%s: invalid seconds '%s'\n", progname, optarg); return EX_USAGE; } break; default: return usage(); } } #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); if (signalg == DKIM_SIGN_UNKNOWN) { if (dkim_libfeature(lib, DKIM_FEATURE_SHA256)) signalg = DKIM_SIGN_RSASHA256; else signalg = DKIM_SIGN_RSASHA1; } else if (signalg == DKIM_SIGN_RSASHA256 && !dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { fprintf(stdout, "### requested signing algorithm not available\n"); dkim_close(lib); return 1; } fprintf(stdout, "*** SIGNING SPEED TEST: %s/%s with %s, size %u for %lds\n", canon_name(hcanon), canon_name(bcanon), alg_name(signalg), (unsigned int) msgsize, (long) testint); key = KEY; srandom(time(NULL)); /* prepare a random body buffer */ for (c = 0, w = 0; c < sizeof body; c++) { if (w >= 75 && c < sizeof body - 2) { body[c++] = '\r'; body[c++] = '\n'; w = 0; } body[c] = (random() % 95) + 32; w++; } (void) time(&start); while (time(NULL) < start + testint) { dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, hcanon, bcanon, signalg, -1L, &status); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); status = dkim_eoh(dkim); msgrem = msgsize; while (msgrem > 0) { wsz = MIN(msgrem, sizeof body); status = dkim_body(dkim, body, wsz); msgrem -= wsz; } (void) dkim_body(dkim, CRLF, 2); status = dkim_eom(dkim, NULL); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); status = dkim_free(dkim); signcnt++; } dkim_close(lib); rate = signcnt / testint; fprintf(stdout, "*** %u messages signed (%d msgs/sec)\n", signcnt, rate); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test00.c000066400000000000000000000105531337314105200236440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 signing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test01.c000066400000000000000000000105501337314105200236420ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test02.c000066400000000000000000000105531337314105200236460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=prwCqoRHu3yS2iwXjn84w3TahetxJ+NefGpfQyjFfhTISiJQUmaiNdy7eYyejQ73v\r\n\t StW5pWXBJfIJVXnaIC0zNBnrK3yjVX2OhzjXCpj/iWTQcZnBmgOKjJ6mpErTVjGR2f\r\n\t xZYXt60f1pxSP3NhdSpuY552n+1DgB0yjVV9LkMI=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/relaxed rsa-sha1 signing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, "test02", NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test03.c000066400000000000000000000105501337314105200236440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=JsoKzXDo/jojk0oiVb+HrXpApPIan7wj+wSuf5S5DtVvsk7nw3SDFNNOxve1yT49U\r\n\t /3ysgE0ArTYWfUuSvvFhRjT9L/3BIyYd1pwmchsu/LBqJwpMPPMCrNwd5B2SiOS8CU\r\n\t AhxmF26t+zi9B3ocqYqk3Ql/dLmXecs4fae5t8Sg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/simple rsa-sha1 signing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, "test03", NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test04.c000066400000000000000000000104701337314105200236460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test05.c000066400000000000000000000104661337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test06.c000066400000000000000000000104711337314105200236510ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=prwCqoRHu3yS2iwXjn84w3TahetxJ+NefGpfQyjFfhTISiJQUmaiNdy7eYyejQ73v\r\n\t StW5pWXBJfIJVXnaIC0zNBnrK3yjVX2OhzjXCpj/iWTQcZnBmgOKjJ6mpErTVjGR2f\r\n\t xZYXt60f1pxSP3NhdSpuY552n+1DgB0yjVV9LkMI=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/relaxed rsa-sha1 verifying\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, "test06", NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test07.c000066400000000000000000000104671337314105200236570ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=JsoKzXDo/jojk0oiVb+HrXpApPIan7wj+wSuf5S5DtVvsk7nw3SDFNNOxve1yT49U\r\n\t /3ysgE0ArTYWfUuSvvFhRjT9L/3BIyYd1pwmchsu/LBqJwpMPPMCrNwd5B2SiOS8CU\r\n\t AhxmF26t+zi9B3ocqYqk3Ql/dLmXecs4fae5t8Sg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/simple rsa-sha1 verifying\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, "test07", NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test08.c000066400000000000000000000110731337314105200236520ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=MGX4UPq8C9b0OStHs/99x1P92eN03t0TXVveQukipj6O67Eie9KZerqH9pmCKgUIf\r\n\t OqxlJf22RlnbCw+FvYPT2nWGWf3o5pHenroLB5Fgu80i/g+xGbD7JkZRJTNUG1Co2t\r\n\t r6q263XUmcXP1tdrr+28AgW9t+U33zWu87UdV3es=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 signing with lengths\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test09.c000066400000000000000000000110701337314105200236500ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; l=343;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q16ySp1zCP92eJ7/A6NATF21BPtDCj14BFXt1/SjG4kJRaMBTIdSRWwV5IDOCQ9uJ\r\n\t ug3UL2OMvLwElBR7XzPiDfgIKBokbo2zoFuJsHw7D3ZVeWKj+Oc/X5+G9oGbXgmp3n\r\n\t rqLZNfKyKnerbYrZsbYXsGZbLFt3Bby1Mu0q9z0g=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with lengths\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test10.c000066400000000000000000000110701337314105200236400ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=b+RDInOs5UiR9nT/+eVBdTH1/v1h/z2Zk0SqfU++Il80GFaWeoVomsrdK22pkXXjz\r\n\t 0SYld8L5jirfnV24d4NO3h5/631Rp1L9jnS7QJ9GxUZQ6Ax+4E+k2Ng7Dpus/VFDdA\r\n\t iC8RxrGDT38tY2r+Fpejj+6sOtL7KEpYOxSBjeng=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/relaxed rsa-sha1 signing with lengths\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test100.c000066400000000000000000000170451337314105200237300ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=Gb2p2FRiCK0vAI+F5+EQ/l\r\n\tKrk9MdARHyw4noadY4R40VJrIrKgUtUL24frvN2NSf3kZaB1Edrksj/TYKsfzyPCUr/\r\n\tTTzf8Q/OWTEHAehsnUWZFK134WpidjMdn0kk1bNeVP7VWeQHgYh8eigji5pqbydusou\r\n\tMtlSHgKtSEKwi5o=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=NiN+5WZz+O0jY\r\n\t+OH1mCVhv3zM+SrJ6i0wTrhoaDOawOTwW10dF/ZTaMdFmrjJkQfxQenKQN0hmxRNm0Q\r\n\tabHoiaaO1N5owKY0/cUV78U5Z05bNjGl9P9goSgNsLGukRgjb+ellUI8U97Xi9mFjOG\r\n\tWm1iJ2FIq31Bh1mybmvlveKA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM *dkim2; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** exercise dkim_minbody()\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); dkim2 = dkim_verify(lib, JOBID, NULL, &status); assert(dkim2 != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim2, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER06, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim2); assert(status == DKIM_STAT_OK); assert(dkim_minbody(dkim) == ULONG_MAX); assert(dkim_minbody(dkim2) == 340); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); assert(dkim_minbody(dkim) == ULONG_MAX); assert(dkim_minbody(dkim2) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); status = dkim_free(dkim2); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test101.c000066400000000000000000000131771337314105200237330ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=NiN+5WZz+O0jY\r\n\t+OH1mCVhv3zM+SrJ6i0wTrhoaDOawOTwW10dF/ZTaMdFmrjJkQfxQenKQN0hmxRNm0Q\r\n\tabHoiaaO1N5owKY0/cUV78U5Z05bNjGl9P9goSgNsLGukRgjb+ellUI8U97Xi9mFjOG\r\n\tWm1iJ2FIq31Bh1mybmvlveKA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; int bits; ssize_t msglen; ssize_t canonlen; ssize_t signlen; dkim_alg_t signalg; uint64_t signtime; dkim_canon_t hcanon; dkim_canon_t bcanon; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** exercise dkim_sig_*() utility functions\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); sig = dkim_getsignature(dkim); assert(sig != NULL); status = dkim_sig_getcanonlen(dkim, sig, &msglen, &canonlen, &signlen); assert(status == DKIM_STAT_OK); assert(msglen == 369); assert(canonlen == 340); assert(signlen == 340); status = dkim_sig_getkeysize(sig, &bits); assert(status == DKIM_STAT_OK); assert(bits == 1024); status = dkim_sig_getsignalg(sig, &signalg); assert(status == DKIM_STAT_OK); assert(signalg == DKIM_SIGN_RSASHA1); status = dkim_sig_getsigntime(sig, &signtime); assert(status == DKIM_STAT_OK); assert(signtime == 1172620939); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_OK); assert(strcmp(dkim_sig_geterrorstr(dkim_sig_geterror(sig)), "no signature error") == 0); status = dkim_sig_getcanons(sig, &hcanon, &bcanon); assert(status == DKIM_STAT_OK); assert(hcanon == DKIM_CANON_RELAXED); assert(bcanon == DKIM_CANON_RELAXED); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test102.c000066400000000000000000000113361337314105200237270ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" char *mustbesigned[] = { "cc", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with \"must be signed\" list\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_MUSTBESIGNED, mustbesigned, sizeof(char **)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER10, strlen(HEADER10)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_MBSFAILED); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test103.c000066400000000000000000000107611337314105200237310ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; x=1172620940; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with expired timestamp (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_EXPIRED); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test104.c000066400000000000000000000107411337314105200237300ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=3199999999; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with future timestamp (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_FUTURE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test105.c000066400000000000000000000042431337314105200237310ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=-1; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with negative timestamp (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test106.c000066400000000000000000000042411337314105200237300ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=now; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bogus timestamp (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test107.c000066400000000000000000000064651337314105200237430ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_canon_t bcanon; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 default body canonicalization\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(sigs != NULL); assert(nsigs != 0); status = dkim_sig_getcanons(sigs[0], NULL, &bcanon); assert(status == DKIM_STAT_OK); assert(bcanon == DKIM_CANON_SIMPLE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test108.c000066400000000000000000000107601337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=bogus/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bogus header canonicalization (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_INVALID_HC); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test109.c000066400000000000000000000107571337314105200237440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/bogus; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bogus body canonicalization (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_INVALID_BC); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test11.c000066400000000000000000000110651337314105200236450ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; l=343;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=R7VQjrlUSzN68m+yzKWlkNhBr5dSKSTnCOo2yH2SAOwVX4ZkwrhbEkX/jchEx3Eij\r\n\t YV0RompOqszSCGs49eBXfk1eo/Cwae3g+Mg126rhgko5z3SDrYVZ8BDYcyEatr3mpG\r\n\t yFVUuI5mzAoubhxIwEXcKA7I46l+gxVMRjygVKj4=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/simple rsa-sha1 signing with lengths\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test110.c000066400000000000000000000107521337314105200237270ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1.0; a=rsa-sha1; c=relaxed/bogus; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bogus signature version (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_VERSION); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test111.c000066400000000000000000000016771337314105200237360ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "../dkim-internal.h" #include "../util.h" #define MAXHEADER 4096 #define QP_IN "root=40example=2E=\r\ncom\n" #define QP_OUT "root@example.com\n" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int olen; char buf[BUFRSZ + 1]; printf("*** quoted-printable decode\n"); olen = dkim_qp_decode(QP_IN, buf, sizeof buf); assert(olen == strlen(QP_OUT)); buf[olen] = '\0'; assert(strcmp(QP_OUT, buf) == 0); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test112.c000066400000000000000000000107051337314105200237270ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com;\r\n\ts=brisbane; t=1172620939; i=msk@sendmail.com; bh=ll/0h2aWgG+D3ewmE4\r\n\tY3pY7Ukz8=; h=subject:to:date; b=k1ZKkMnlh62VdAwa3umwZf6yhF9TWF4PERI5OXKoxU2TAtvwNZ6Q\r\n\tLMlELWHEG0Q1OORyb4cpQPfgGdOc6m38r0o/+k4rvlwnWsejpMWJgd4mD4e6U0b+pEt\r\n\txO704bDKUlzV83MAqIN/QdxW5dvwOyr1/1OrVu2fTUlUp6SWaa2o=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_SIGINFO *sig; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with i=/d= mismatch (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_DOMAIN); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test113.c000066400000000000000000000056221337314105200237320ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ struct dkim_dstring; /* libopendkim includes */ #include "../dkim-internal.h" #include "../dkim-util.h" #define TESTBUFRSZ 4096 #define TESTJOBID "x" #define TESTSTRING "Hello, world!\n" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int c; DKIM_STAT status; DKIM_LIB *lib; DKIM *dkim; struct dkim_dstring *dstring; char *p; char testbuf[TESTBUFRSZ + 1]; printf("*** exercise dstring functions\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); dkim = dkim_verify(lib, TESTJOBID, NULL, &status); assert(dkim != NULL); /* make a dstring */ dstring = dkim_dstring_new(dkim, 0, 0); assert(dstring != NULL); /* confirm that it's empty */ assert(dkim_dstring_len(dstring) == 0); p = dkim_dstring_get(dstring); assert(p != NULL); assert(p[0] == '\0'); /* put something in it */ for (c = 0; c < sizeof testbuf; c++) testbuf[c] = (random() % 94) + 32; testbuf[sizeof testbuf - 1] = '\0'; assert(dkim_dstring_copy(dstring, testbuf)); assert(dkim_dstring_len(dstring) == sizeof testbuf - 1); p = dkim_dstring_get(dstring); assert(p != NULL); assert(strlen(p) == sizeof testbuf - 1); assert(strcmp(p, testbuf) == 0); /* blank it */ dkim_dstring_blank(dstring); p = dkim_dstring_get(dstring); assert(p != NULL); assert(p[0] == '\0'); /* put something small in it using "cat" */ assert(dkim_dstring_cat(dstring, TESTSTRING)); p = dkim_dstring_get(dstring); assert(p != NULL); assert(strcmp(p, TESTSTRING) == 0); assert(dkim_dstring_cat(dstring, TESTSTRING)); p = dkim_dstring_get(dstring); assert(p != NULL); assert(strcmp(p, TESTSTRING TESTSTRING) == 0); /* try cat1 */ dkim_dstring_blank(dstring); assert(dkim_dstring_cat1(dstring, 'H')); assert(dkim_dstring_len(dstring) == 1); p = dkim_dstring_get(dstring); assert(p != NULL); assert(strcmp(p, "H") == 0); /* try catn */ dkim_dstring_blank(dstring); assert(dkim_dstring_catn(dstring, TESTSTRING, 5)); assert(dkim_dstring_len(dstring) == 5); p = dkim_dstring_get(dstring); assert(p != NULL); assert(strcmp(p, "Hello") == 0); /* start over */ dkim_dstring_free(dstring); dstring = dkim_dstring_new(dkim, 0, (sizeof testbuf) / 2); assert(dstring != NULL); /* try an oversized append */ assert(!dkim_dstring_copy(dstring, testbuf)); /* clean up */ dkim_dstring_free(dstring); dkim_free(dkim); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test114.c000066400000000000000000000400551337314105200237320ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 /* template */ #define SIG "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG1 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; l=-1; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG3 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; l=all; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG4 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; q=foo; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG5 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; q=dns/foo; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG6 "v=1; a=rsa-sha1; c=relaxed/simple; s=test;\r\n\tt=1172620939; q=dns/foo; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG7 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; \r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG8 "v=1; a=rsa-sha1; c=relaxed/simple; d=; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG9 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG10 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG11 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG12 "v=1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG13 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID" #define SIG14 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=" #define SIG15 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8f=" #define SIG16 "v=1; a=rsa-sha0; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG17 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=; x" #define SIG18 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=%ld; x=%ld; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG19 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; x=never; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG20 "v=1; =rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG21 "v=1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG22 "v=1; a=rsa-sha1; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG23 "a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nsigs; int len; DKIM_STAT status; dkim_canon_t bcanon; dkim_canon_t hcanon; time_t now; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** detection of various signature abnormalities\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); /* missing h= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* negative l= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* bogus l= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG3); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* bogus q= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG4); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* bogus q= option */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG5); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* missing d= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG6); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* missing s= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG7); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* empty d= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG8); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* empty s= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG9); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* missing bh= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG10); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* empty bh= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG11); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* missing a= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG12); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* missing b= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG13); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* empty b= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG14); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* corrupt b= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG15); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* invalid a= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG16); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* trailing tag with no value */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG17); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* x= < t= */ (void) time(&now); len = snprintf(hdr, sizeof hdr, "%s: ", DKIM_SIGNHEADER); snprintf(hdr + len, sizeof hdr - len, SIG18, (long) (now + 25), (long) (now + 10)); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* bogus x= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG19); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* control characters */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG20); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* missing a= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG21); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); /* missing c= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG22); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* missing v= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG23); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 13); assert(dkim_sig_geterror(sigs[0]) == DKIM_SIGERROR_INVALID_L); assert(dkim_sig_geterror(sigs[1]) == DKIM_SIGERROR_INVALID_L); assert(dkim_sig_geterror(sigs[2]) == DKIM_SIGERROR_INVALID_Q); assert(dkim_sig_geterror(sigs[3]) == DKIM_SIGERROR_INVALID_QO); assert(dkim_sig_geterror(sigs[4]) == DKIM_SIGERROR_EMPTY_D); assert(dkim_sig_geterror(sigs[5]) == DKIM_SIGERROR_EMPTY_S); assert(dkim_sig_geterror(sigs[6]) == DKIM_SIGERROR_MISSING_BH); assert(dkim_sig_geterror(sigs[7]) == DKIM_SIGERROR_EMPTY_BH); assert(dkim_sig_geterror(sigs[8]) == DKIM_SIGERROR_EMPTY_B); assert(dkim_sig_geterror(sigs[9]) == DKIM_SIGERROR_CORRUPT_B); assert(dkim_sig_geterror(sigs[10]) == DKIM_SIGERROR_INVALID_A); assert(dkim_sig_geterror(sigs[11]) == DKIM_SIGERROR_TIMESTAMPS); assert(dkim_sig_geterror(sigs[12]) == DKIM_SIGERROR_BADSIG); status = dkim_sig_getcanons(sigs[12], &hcanon, &bcanon); assert(status == DKIM_STAT_OK); assert(hcanon == DKIM_CANON_SIMPLE); assert(bcanon == DKIM_CANON_SIMPLE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test115.c000066400000000000000000000171421337314105200237340ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=nok;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=badv;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG3 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=sha256only;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG4 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=badh;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG5 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=badk;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG6 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=nop;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG7 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=emptyp;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG8 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=corruptp;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** detection of various key anomalies\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); /* key with no k= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key with bad v= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key allowing sha256 only */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG3); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key with bogus h= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG4); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key with bogus k= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG5); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key with missing p= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG6); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key with empty p= (revoked) */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG7); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); /* key with corrupt p= */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG8); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 8); assert(dkim_sig_geterror(sigs[0]) == DKIM_SIGERROR_BADSIG); assert(dkim_sig_geterror(sigs[1]) == DKIM_SIGERROR_KEYVERSION); if (dkim_libfeature(lib, DKIM_FEATURE_SHA256)) assert(dkim_sig_geterror(sigs[2]) == DKIM_SIGERROR_KEYHASHMISMATCH); else assert(dkim_sig_geterror(sigs[2]) == DKIM_SIGERROR_KEYUNKNOWNHASH); assert(dkim_sig_geterror(sigs[3]) == DKIM_SIGERROR_KEYUNKNOWNHASH); assert(dkim_sig_geterror(sigs[4]) == DKIM_SIGERROR_KEYTYPEUNKNOWN); assert(dkim_sig_geterror(sigs[5]) == DKIM_SIGERROR_DNSSYNTAX); assert(dkim_sig_geterror(sigs[6]) == DKIM_SIGERROR_KEYREVOKED); assert(dkim_sig_geterror(sigs[7]) == DKIM_SIGERROR_KEYDECODE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test116.c000066400000000000000000000050001337314105200237230ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; printf("*** verifying unsigned message\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_NOSIG); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_NOSIG); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test117.c000066400000000000000000000146161337314105200237410ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim-internal.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" char *senderhdrs[] = { "from", "sender", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ u_int test_uint; u_int timeout; uint64_t fixed_time; uint64_t test_time; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; char **testarray; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; char path[MAXPATHLEN + 1]; char *td = NULL; printf("*** general utility functions\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); /* exercise some dkim_options() stuff */ status = dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_TMPDIR, path, sizeof path); assert(status == DKIM_STAT_OK); td = getenv("DKIM_TMPDIR"); if (td == NULL || td[0] == '\0') td = DEFTMPDIR; assert(strcmp(path, td) == 0); fixed_time = 1172620939; status = dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); assert(status == DKIM_STAT_OK); status = dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FIXEDTIME, &test_time, sizeof test_time); assert(status == DKIM_STAT_OK); assert(test_time == fixed_time); fixed_time = 300; status = dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNATURETTL, &fixed_time, sizeof fixed_time); assert(status == DKIM_STAT_OK); status = dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_SIGNATURETTL, &test_time, sizeof test_time); assert(status == DKIM_STAT_OK); assert(test_time == fixed_time); fixed_time = 600; status = dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_CLOCKDRIFT, &fixed_time, sizeof fixed_time); assert(status == DKIM_STAT_OK); status = dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_CLOCKDRIFT, &test_time, sizeof test_time); assert(status == DKIM_STAT_OK); assert(test_time == fixed_time); timeout = 5; status = dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_TIMEOUT, &timeout, sizeof timeout); assert(status == DKIM_STAT_OK); status = dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_TIMEOUT, &test_uint, sizeof test_uint); assert(status == DKIM_STAT_OK); assert(test_uint == timeout); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); assert(dkim_getmode(dkim) == DKIM_MODE_VERIFY); assert(strcmp(dkim_getuser(dkim), USER) == 0); assert(strcmp(dkim_getdomain(dkim), DOMAIN2) == 0); assert(dkim_geterror(dkim) == NULL); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test118.c000066400000000000000000000110621337314105200237320ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "../dkim-test.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define KEYNAME "test._domainkey.example.com" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; dkim_query_t qtype = DKIM_QUERY_FILE; DKIM *dkim; DKIM_LIB *lib; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with simulated DNS\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); /* queue up a DNS reply for the key */ status = dkim_test_dns_put(dkim, C_IN, T_TXT, 0, KEYNAME, PUBLICKEY); assert(status == 0); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test119.c000066400000000000000000000062661337314105200237450ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verify failure with EOH check SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verify failure with EOH check\n"); /* set flags */ flags = DKIM_LIBFLAGS_EOHCHECK; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_CANTVRFY); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test12.c000066400000000000000000000111561337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=NiN+5WZz+O0jY\r\n\t+OH1mCVhv3zM+SrJ6i0wTrhoaDOawOTwW10dF/ZTaMdFmrjJkQfxQenKQN0hmxRNm0Q\r\n\tabHoiaaO1N5owKY0/cUV78U5Z05bNjGl9P9goSgNsLGukRgjb+ellUI8U97Xi9mFjOG\r\n\tWm1iJ2FIq31Bh1mybmvlveKA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying with lengths plus extra data\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test120.c000066400000000000000000000124071337314105200237270ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test; t=1172620939; bh=WAB3bZtTHYLitirqQFGpaOBbkVY=; h=Content-class:Subject:Thread-Index:Date:X-MS-Has-Attach:From:To:Reply-To; b=gPbK/km0cEiwJBTjSUQ0oioRQNBMCJ6y6mSvg6S2z8xM57/BZx7I7c+eZ6IwtmCAXRMXJqiRixr9bxpcRU6KVkje3ofytiQ35bY7+h6RpV61lBFDxbMzdZfRmseGGeZGcGmmp6ICfi18f3KCiTOUrDptZ3+MVxSVeIdnVM6cLQ8=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; dkim_query_t qtype = DKIM_QUERY_FILE; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; unsigned char inhdr[MAXHEADER + 1]; printf("*** zero margin testing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID "s1", NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); status = dkim_set_margin(dkim, 0); assert(status == DKIM_STAT_OK); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); #define HEADER0 "Content-class: urn:content-classes:message" #define HEADER1 "Subject: This is a sample message from a DKIM tester" #define HEADER2 "Thread-Index: 1234567tgjdoigj" #define HEADER3 "Date: Wed, 18 Jul 2007 10:48:38 -0700" #define HEADER4 "X-MS-Has-Attach:" #define HEADER5 "From: \"DKIM tester\" " #define HEADER6 "To: \"DKIM tester\" " #define HEADER7 "Reply-To: \"DKIM tester\" " #define BODY "Test\r\n" status = dkim_header(dkim, HEADER0, strlen(HEADER0)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER1, strlen(HEADER1)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER2, strlen(HEADER2)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER3, strlen(HEADER3)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER4, strlen(HEADER4)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER5, strlen(HEADER5)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER6, strlen(HEADER6)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER7, strlen(HEADER7)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY, strlen(BODY)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, 0); assert(status == DKIM_STAT_OK); assert(strcmp(SIG1, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID "v1", NULL, &status); assert(dkim != NULL); status = dkim_set_margin(dkim, 0); assert(status == DKIM_STAT_INVALID); snprintf(inhdr, sizeof inhdr, "%s: %s", DKIM_SIGNHEADER, hdr); status = dkim_header(dkim, inhdr, strlen(inhdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER0, strlen(HEADER0)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER1, strlen(HEADER1)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER2, strlen(HEADER2)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER3, strlen(HEADER3)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER4, strlen(HEADER4)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER5, strlen(HEADER5)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER6, strlen(HEADER6)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER7, strlen(HEADER7)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY, strlen(BODY)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_set_margin(dkim, DKIM_HDRMARGIN); assert(status == DKIM_STAT_INVALID); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test121.c000066400000000000000000000042231337314105200237250ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=Gb2p2FRiCK0vAI+F5+EQ/l\r\n\tKrk9MdARHyw4noadY4R40VJrIrKgUtUL24frvN2NSf3kZaB1Edrksj/TYKsfzyPCUr/\r\n\tTTzf8Q/OWTEHAehsnUWZFK134WpidjMdn0kk1bNeVP7VWeQHgYh8eigji5pqbydusou\r\n\tMtlSHgKtSEKwi5o=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying with empty \"t=\"\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test122.c000066400000000000000000000103171337314105200237270ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define GIBBERISHLEN (sizeof(GIBBERISH) - 1) #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=5Z5kUG7FTM/P2DzvDVOdFzOUr6m33zc4K5qzpwn+jTc=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=qtj/DXxof5Ek/8aSXCGkyqpRCAviW6vmwx9feqGq/OnxMwYwCbwa5TOayfJHGdL1/\r\n\t IK7GL77WMa/Jn0d580YG/qS+wOE2cWas3rR2xnPwvjXpUr8ck/xMH8R79mEWbZ+wTT\r\n\t v0mKf0YcpyicBf+Y/OBQW930kmIqPzo1/qfwWhgc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { size_t llen = 0; size_t wlen = LARGEBODYSIZE; # ifdef TEST_KEEP_FILES u_int flags; # endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; u_char *p; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char gibline[sizeof(GIBBERISH) + 1]; unsigned char hdr[MAXHEADER + 1]; unsigned char body[LARGEBODYSIZE]; strlcpy(gibline, GIBBERISH, sizeof gibline); p = strchr(gibline, '\r'); if (p != NULL) *p = '\0'; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing large lines SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing large lines\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); memset(body, '\0', sizeof body); while (wlen > GIBBERISHLEN + 2) { strlcat(body, gibline, sizeof body); wlen -= strlen(gibline); llen += strlen(gibline); if (llen > LARGELINESIZE) { strlcat(body, CRLF, sizeof body); wlen -= 2; llen = 0; } } strlcat(body, CRLF, sizeof body); status = dkim_body(dkim, body, strlen(body)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test123.c000066400000000000000000000100771337314105200237330ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define GIBBERISHLEN (sizeof(GIBBERISH) - 1) #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=5Z5kUG7FTM/P2DzvDVOdFzOUr6m33zc4K5qzpwn+jTc=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=qtj\r\n\t/DXxof5Ek/8aSXCGkyqpRCAviW6vmwx9feqGq/OnxMwYwCbwa5TOayfJHGdL1/IK7GL\r\n\t77WMa/Jn0d580YG/qS+wOE2cWas3rR2xnPwvjXpUr8ck/xMH8R79mEWbZ+wTTv0mKf0\r\n\tYcpyicBf+Y/OBQW930kmIqPzo1/qfwWhgc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { size_t llen = 0; size_t wlen = LARGEBODYSIZE; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; u_char *p; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char gibline[sizeof(GIBBERISH) + 1]; unsigned char hdr[MAXHEADER + 1]; unsigned char body[LARGEBODYSIZE]; strlcpy(gibline, GIBBERISH, sizeof gibline); p = strchr(gibline, '\r'); if (p != NULL) *p = '\0'; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying large lines SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying large lines\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); memset(body, '\0', sizeof body); while (wlen > GIBBERISHLEN + 2) { strlcat(body, gibline, sizeof body); wlen -= strlen(gibline); llen += strlen(gibline); if (llen > LARGELINESIZE) { strlcat(body, CRLF, sizeof body); wlen -= 2; llen = 0; } } strlcat(body, CRLF, sizeof body); status = dkim_body(dkim, body, strlen(body)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test125.c000066400000000000000000000064421337314105200237360ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG7 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=emptyp;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** handling of revoked keys\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); /* key with empty p= (revoked) */ snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG7); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 1); assert(dkim_sig_geterror(sigs[0]) == DKIM_SIGERROR_KEYREVOKED); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_REVOKED); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test126.c000066400000000000000000000110361337314105200237320ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=EBrBEVXN6K4mYL9hlwuH9QUz/ScedtOv59DF4mtjZZmWF3qz5yrXNYC+t6fw+Gt1a\r\n\t WURx7hTgcFXhTo2b36SWxkQ2Eu5G3ZHKmvv88rEODR0drhf6zZhVPL3woXtcsoBQ9l\r\n\t mrhop/ejJJ+IWFMIeaFxTUlWoSK6C50fC+83nb+E=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying with implicit body canonicalization SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying with implicit body canonicalization\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test127.c000066400000000000000000000074541337314105200237440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define MAXMSGSIZE 16384 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=NYK+FZAKLNXv1Oj/E6kV0EOStBU=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=G9BZ+aZqLU7j3DnHe1s/qgrJagml7UDFUxOEQ/uCwWGvOgrDn3PBE/Nb1OwpGzuFJ\r\n\t AOCTpNGrK2sw4pfEAk+/uOBGjZsMTBe9uqIA7w3tQFkF3yIRv6zqa/rccbWa5d0wYn\r\n\t S534UHVEyPXjXQ5x/yspDXF+v3geyISQ+oHf9hro=" #define CRLFBODY00 "test\r\n" #define BOUNDARY 9 /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; unsigned char buf[MAXMSGSIZE]; printf("*** relaxed/simple rsa-sha1 signing with split CRLFs and blank counting\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); memset(buf, '\0', sizeof buf); strlcpy(buf, CRLFBODY00, sizeof buf); while (strlen(buf) < BOUNDARY) strlcat(buf, CRLF, sizeof buf); strlcat(buf, CRLFBODY00, sizeof buf); assert(strlen(buf) > BOUNDARY); status = dkim_body(dkim, buf, BOUNDARY); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, buf + BOUNDARY, strlen(buf) - BOUNDARY); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test128.c000066400000000000000000000210451337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; dkim_sigkey_t key; DKIM *dkim; DKIM *resign; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char hdr2[MAXHEADER + 1]; key = KEY; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_RESIGN)) { printf("*** relaxed/simple rsa-sha1 re-signing with header binding SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha1 re-signing with header binding\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ /* test mode */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* restrict signed headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, dkim_should_signhdrs, sizeof(u_char **)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); resign = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(resign != NULL); status = dkim_resign(dkim, resign, TRUE); assert(status == DKIM_STAT_INVALID); status = dkim_resign(resign, dkim, TRUE); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_eoh(resign); assert(status == DKIM_STAT_INVALID); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(resign, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_INVALID); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(resign, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_eom(resign, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(resign, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_INVALID); status = dkim_free(resign); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); /* now see if that one was valid */ dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr2, sizeof hdr2, "%s: %s", DKIM_SIGNHEADER, hdr); status = dkim_header(dkim, hdr2, strlen(hdr2)); assert(status == DKIM_STAT_OK); snprintf(hdr2, sizeof hdr2, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr2, strlen(hdr2)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test129.c000066400000000000000000000246711337314105200237460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define AUTHRESHDR "Authentication-Results" #define AUTHRESVAL "example.net; dkim=pass header.i=@example.com" #define JOBID1 "testing1" #define JOBID2 "testing2" #define JOBID3 "testing3" #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* list of headers to sign */ const u_char *signhdrs[] = { "from", "sender", "reply-to", "subject", "date", "message-id", "to", "cc", "mime-version", "content-type", "content-transfer-encoding", "content-id", "content-description", "resent-date", "resent-from", "resent-sender", "resent-to", "resent-cc", "resent-message-id", "in-reply-to", "references", "list-id", "list-help", "list-unsubscribe", "list-subscribe", "list-post", "list-owner", "list-archive", "authentication-results", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; dkim_sigkey_t key; DKIM *dkim; DKIM *resign; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char hdr2[MAXHEADER + 1]; key = KEY; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_RESIGN)) { printf("*** relaxed/simple rsa-sha1 re-signing without header binding SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha1 re-signing without header binding\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ /* test mode */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* restrict signed headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, signhdrs, sizeof(u_char **)); dkim = dkim_verify(lib, JOBID1, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); resign = dkim_sign(lib, JOBID2, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(resign != NULL); status = dkim_resign(dkim, resign, TRUE); assert(status == DKIM_STAT_INVALID); status = dkim_resign(resign, dkim, FALSE); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(resign, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(resign, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(resign, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_INVALID); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(resign, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", AUTHRESHDR, AUTHRESVAL); status = dkim_header(resign, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_eoh(resign); assert(status == DKIM_STAT_OK); status = dkim_eom(resign, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(resign, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_INVALID); status = dkim_free(resign); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); /* now see if that one was valid */ dkim = dkim_verify(lib, JOBID3, NULL, &status); assert(dkim != NULL); snprintf(hdr2, sizeof hdr2, "%s: %s", DKIM_SIGNHEADER, hdr); status = dkim_header(dkim, hdr2, strlen(hdr2)); assert(status == DKIM_STAT_OK); snprintf(hdr2, sizeof hdr2, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr2, strlen(hdr2)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", AUTHRESHDR, AUTHRESVAL); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test13.c000066400000000000000000000111541337314105200236460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; l=343; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=CZFpuHw59Yu1v\r\n\tIslROlWMhFSMOkRxv9hj5Ak10lAhOGtlyL0o5y6nBBujSb5gzYIw8mabKAgYNSFo3oF\r\n\tbLaupzTSRoqTL5PEvRiEIj/R5s8vLJ0Mpeil1TZPHCmhWuMSepecoKWrRX9hPFxsuQa\r\n\t34l3/+z1BReWgByVZRQ91w2Y=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with lengths plus extra data\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test130.c000066400000000000000000000105301337314105200237230ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha1; c=relaxed; d=example.com;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG3 "a=rsa-sha1; c=relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 with bad/good signatures\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags */ flags = DKIM_LIBFLAGS_BADSIGHANDLES; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG3); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(sigs != NULL); assert(nsigs == 3); assert(dkim_sig_geterror(sigs[0]) == DKIM_SIGERROR_MISSING_S); assert(strcmp(dkim_sig_getdomain(sigs[0]), DOMAIN) == 0); assert(dkim_sig_geterror(sigs[2]) == DKIM_SIGERROR_MISSING_V); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test131.c000066400000000000000000000146201337314105200237300ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define NULLBH "bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=" /* ** EATWS -- eat whitespace ** ** Parameters: ** str -- string to crush ** ** Return value: ** None. */ void eatws(char *str) { char *p; char *q; for (p = str, q = str; *p != '\0'; p++) { if (!isascii(*p) || !isspace(*p)) { *q = *p; q++; } } *q = '\0'; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; u_char *p; char *last; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; unsigned char hdr2[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/relaxed rsa-sha256 body blank reduction SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/relaxed rsa-sha256 body blank reduction\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); strlcpy(hdr2, hdr, sizeof hdr2); for (p = strtok_r(hdr2, ";", &last); p != NULL; p = strtok_r(NULL, ";", &last)) { eatws(p); if (strncmp(p, "bh=", 3) == 0) assert(strcmp(p, NULLBH) == 0); } status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, CRLF, 2); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr2, '\0', sizeof hdr2); status = dkim_getsighdr(dkim, hdr2, sizeof hdr2, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(hdr2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, CRLF CRLF SP SP CRLF, 2); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr2, '\0', sizeof hdr2); status = dkim_getsighdr(dkim, hdr2, sizeof hdr2, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(hdr2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test132.c000066400000000000000000000114331337314105200237300ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com;\r\n\ts=brisbane; t=1172620939; i=msk@sendmail.com; bh=ll/0h2aWgG+D3ewmE4\r\n\tY3pY7Ukz8=; h=subject:to:date; b=k1ZKkMnlh62VdAwa3umwZf6yhF9TWF4PERI5OXKoxU2TAtvwNZ6Q\r\n\tLMlELWHEG0Q1OORyb4cpQPfgGdOc6m38r0o/+k4rvlwnWsejpMWJgd4mD4e6U0b+pEt\r\n\txO704bDKUlzV83MAqIN/QdxW5dvwOyr1/1OrVu2fTUlUp6SWaa2o=" #define IDENT "msk@sendmail.com" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_SIGINFO *sig; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char smallbuf[8]; unsigned char largebuf[1024]; unsigned char hdr[MAXHEADER + 1]; printf("*** testing dkim_sig_getidentity()\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); memset(largebuf, '\0', sizeof largebuf); status = dkim_sig_getidentity(dkim, sig, smallbuf, sizeof smallbuf); assert(status == DKIM_STAT_NORESOURCE); assert(memcmp(smallbuf, IDENT, sizeof smallbuf) == 0); status = dkim_sig_getidentity(dkim, sig, largebuf, sizeof largebuf); assert(status == DKIM_STAT_OK); assert(strcmp(largebuf, IDENT) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test133.c000066400000000000000000000013171337314105200237310ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { unsigned long libversion; printf("*** testing dkim_libversion()\n"); libversion = dkim_libversion(); assert(libversion == OPENDKIM_LIB_VERSION); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test134.c000066400000000000000000000063731337314105200237410ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=enormousdomainabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with oversized domain name\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_NORESOURCE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test135.c000066400000000000000000000032741337314105200237370ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; printf("*** relaxed/simple rsa-sha1 verifying using chunking API (leading CRLF)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test136.c000066400000000000000000000115511337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** LOWERHDR -- lowercase-ize a header field name ** ** Parameters: ** str -- string to update ** ** Return value: ** None. */ void lowerhdr(char *str) { char *p; assert(str != NULL); for (p = str; *p != ':' && *p != '\0'; p++) { if (isupper(*p)) *p = tolower(*p); } } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying with header field name case change\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); strlcpy(hdr, HEADER01, sizeof hdr); lowerhdr(hdr); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test137.c000066400000000000000000000152421337314105200237370ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=V+wiYd1cE70A40eDNUtYwU\r\n\tvqi727NN/vVo/OdC7jG4zvztIXCRjPKDXEfiZdW+6PZ08M4zA3GmLZI2p+IJTza+VDQ\r\n\tbohnvIUSRR6q9+Nddqz1qTCL0gNM5d64xKwrLUesk/3wb/Cvua6Atr+VBMFVCwQmSDf\r\n\trs4brLkqMyFOkCE=" #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=12345678Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" #define SIG3 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=12345678Y4y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nsigs; size_t hdrlen; DKIM_STAT status; DKIM *dkim; DKIM_SIGINFO **sigs; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 signature substrings SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying signature substrings\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 2); memset(hdr, '\0', sizeof hdr); hdrlen = sizeof hdr - 1; status = dkim_get_sigsubstring(dkim, sigs[0], hdr, &hdrlen); assert(status == DKIM_STAT_OK); assert(hdrlen == 8); assert(strcmp(hdr, "V+wiYd1c") == 0); status = dkim_get_sigsubstring(dkim, sigs[1], hdr, &hdrlen); assert(status == DKIM_STAT_OK); assert(hdrlen == 8); assert(strcmp(hdr, "12345678") == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG3); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 3); memset(hdr, '\0', sizeof hdr); hdrlen = sizeof hdr - 1; status = dkim_get_sigsubstring(dkim, sigs[0], hdr, &hdrlen); assert(status == DKIM_STAT_OK); assert(hdrlen == 10); assert(strcmp(hdr, "V+wiYd1cE7") == 0); status = dkim_get_sigsubstring(dkim, sigs[1], hdr, &hdrlen); assert(status == DKIM_STAT_OK); assert(hdrlen == 10); assert(strcmp(hdr, "12345678Y3") == 0); status = dkim_get_sigsubstring(dkim, sigs[2], hdr, &hdrlen); assert(status == DKIM_STAT_OK); assert(hdrlen == 10); assert(strcmp(hdr, "12345678Y4") == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test138.c000066400000000000000000000121711337314105200237360ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIGARRAY 10 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; u_int nsigs; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char signedhdrs[SIGARRAY][DKIM_MAXHEADER + 1]; printf("*** signed header content extraction\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER10, strlen(HEADER10)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); sig = dkim_getsignature(dkim); assert(sig != NULL); nsigs = SIGARRAY; status = dkim_sig_getsignedhdrs(dkim, sig, (u_char *) signedhdrs, DKIM_MAXHEADER + 1, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 8); assert(strcmp(signedhdrs[0], HEADER04) == 0); assert(strcmp(signedhdrs[1], HEADER03) == 0); assert(strcmp(signedhdrs[2], HEADER02) == 0); assert(strcmp(signedhdrs[3], HEADER05) == 0); assert(strcmp(signedhdrs[4], HEADER06) == 0); assert(strcmp(signedhdrs[5], HEADER07) == 0); assert(strcmp(signedhdrs[6], HEADER08) == 0); assert(strcmp(signedhdrs[7], HEADER09) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test139.c000066400000000000000000000104611337314105200237370ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID:From;\r\n\tb=RvWqtJbgK3zK97zc8zGtuu90bZh0ytXhgfGzYzY+aOPK1Uq0jIvBvNLzDUBucQoII\r\n\t hjhzo0hMd0p2IcVkuWAG46vVxwrs7lfDjLnh6KbrpWyKCrcfve9I2SsFAHf68odc5y\r\n\t hapNm/weWJHWqdSUoxMqiFVuFChRsEXzsKDh5ffo=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying with oversigning\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test14.c000066400000000000000000000111541337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=N9ihI7ljeT1HX\r\n\tfaxtBpcCOY3bN8NATibNFMjht68woqOfDLidJVJmqax7wjr8luwmXEY2TK06hLNB1zl\r\n\tTikkkApJP7oKvMimkc3L2h/uZ02ZMedtXanWi6Tdd+39WIE1baUeXoeMTCGe5PWm0+i\r\n\tv+1G0FGHmrZf6uQeB6+VWNSU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/relaxed rsa-sha1 verifying with lengths plus extra data\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test140.c000066400000000000000000000107651337314105200237360ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; foo=bar; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=EVdrR7ZmtS41Max1cC19k6sUZx2QUpn/SmcJ4xJjcsvYYJzabx8yAbo30fWPHYuXZ\r\n\t eev7e/9wRwbCTzejwag9CkDaNxqLIEHnheby73XbA2pzAtY5EMFk5WZuWilDCwH3f2\r\n\t BJ0liJoaw1mDrlUH7SvxsStcqm1npWv4yEQkKkGY=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); printf("*** relaxed/relaxed rsa-sha1 signing with extension tags\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* add an "extension tag" */ status = dkim_add_xtag(dkim, "foo", "bar"); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test141.c000066400000000000000000000117711337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=From:To:Date:Subject;\r\n\tz=From:=20Murray=20S.=20Kucherawy=20|To:=20Sendma\r\n\t il=20Test=20Address=20|Date:=20Thu,=2005=20M\r\n\t ay=202005=2011:59:09=20-0700|Subject:=20DKIM=20test=20message;\r\n\tb=Zmf0/xi9CoU+UUkR76Es1p8Xip2e+56Y6fDiB+Qg7iNj7oMtXnSdcF7z/Mh4Exd6e\r\n\t f1z5kFvmfZFt91EVcYxM5lMy4jxBT++bUPYngJ5JZeTf2qaQt4zjjjZy7qzHikWU6w\r\n\t aMf3sqVa3PvFkyScaP3651n1wfXwYm6cRjgz7KJE=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags = 0; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing with z-tags SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing with constrained z-tags\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_ZTAGS); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* arrange to sign specific headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, dkim_should_signhdrs, sizeof(char **)); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test142.c000066400000000000000000000100311337314105200237220ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define MAXMSGSIZE 16384 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_char *p; size_t len; u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char buf[MAXMSGSIZE]; printf("*** relaxed/simple rsa-sha1 verifying using chunking API (single chunk, LF only, FIXCRLF)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags */ flags = DKIM_LIBFLAGS_FIXCRLF; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); memset(buf, '\0', sizeof buf); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); strlcpy(buf, hdr, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER01, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER02, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER03, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER04, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER05, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER06, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER07, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER08, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER09, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, BODY00, MAXMSGSIZE); strlcat(buf, BODY01, MAXMSGSIZE); strlcat(buf, BODY01A, MAXMSGSIZE); strlcat(buf, BODY01B, MAXMSGSIZE); strlcat(buf, BODY01C, MAXMSGSIZE); strlcat(buf, BODY01D, MAXMSGSIZE); strlcat(buf, BODY01E, MAXMSGSIZE); strlcat(buf, BODY02, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY04, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY05, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); len = strlen(buf); for (p = buf; *p != '\0'; ) { if (*p == '\r') { memmove(p, p + 1, len); len--; } else { p++; } } status = dkim_chunk(dkim, buf, strlen(buf)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_chunk(dkim, NULL, 0); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test143.c000066400000000000000000000067001337314105200237330ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ u_int nqi; u_int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; DKIM_QUERYINFO **qi; DKIM_SIGINFO **sigs; unsigned char hdr[MAXHEADER + 1]; printf("*** test DKIM_QUERYINFO routines\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 1); status = dkim_sig_getqueries(dkim, sigs[0], &qi, &nqi); assert(status == DKIM_STAT_OK); assert(nqi == 1); assert(strcmp(dkim_qi_getname(qi[0]), "test._domainkey.example.com") == 0); assert(dkim_qi_gettype(qi[0]) == 16); free(qi[0]); free(qi); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test144.c000066400000000000000000000116551337314105200237410ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define BADKEY "-----BEGIN RSA PRIVATE KEY-----" \ "MIICXQIBAAKBgQC4GUGr*d/6SFNzVLYpphnRd0QPGKz2uWnV65RAxa1Pw352Bqiz" \ "qiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFgF0gu3UJbNnu3+cd8k/kiQj+q" \ "4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3Dyc079gSLtnSrgXb+gQIDAQAB" \ "AoGAemlI0opm1Kvs2T4VliH8/tvX5FXbBH8LEZQAUwVeFTB/UQlieXyCV39pIxZO" \ "0Sa50qm8YNL9rb5HTSZiHQFOwyAKNqS4m/7JCsbuH4gQkPgPF561BHNL9oKfYgJq" \ "9P4kEFfDTBoXKBMxwWtT7AKV8dYvCa3vYzPQ/1BnqQdw2zECQQDyscdgR9Ih59PQ" \ "b72ddibdsxS65uXS2vzYLe7SKl+4R5JgJzw0M6DTAnoYFf6JAsKGZM15PCC0E16t" \ "RRo47U9VAkEAwjEVrlQ0/8yPACbDggDJg/Zz/uRu1wK0zjqj4vKjleubaX4SEvj7" \ "r6xxZm9hC1pMJAC9y3bbkbgCRBjXfyY6fQJBANe5aq2MaZ41wTOPf45NjbKXEiAo" \ "SbUpboKCIbyyaa8V/2h0t7D3C0dE9l4efsguqdZoF7Rh2/f1F70QpYRgfJkCQQCH" \ "oRrAeGXP50JVW72fNgeJGH/pnghgOa6of0JpxwhENJuGMZxUDfxTtUA6yD3iXP3j" \ "A3WL/wbaHsfOYf9Y+g1NAkAGLhx67Ah+uBNK4Xvfz0YPGINX20m+CMsxAw7FOaNv" \ "IW2oWFfZCB4APkIis79Ql45AHpavwx5XodBMzZwJUvlL\n" \ "-----END RSA PRIVATE KEY-----\n" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** signing attempt with an invalid key\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = BADKEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_NORESOURCE); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_INVALID); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test145.c000066400000000000000000000050001337314105200237250ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define BADKEY "-----BEGIN RSA PRIVATE KEY-----" \ "MIICXQIBAAKBgQC4GUGr*d/6SFNzVLYpphnRd0QPGKz2uWnV65RAxa1Pw352Bqiz" \ "qiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFgF0gu3UJbNnu3+cd8k/kiQj+q" \ "4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3Dyc079gSLtnSrgXb+gQIDAQAB" \ "AoGAemlI0opm1Kvs2T4VliH8/tvX5FXbBH8LEZQAUwVeFTB/UQlieXyCV39pIxZO" \ "0Sa50qm8YNL9rb5HTSZiHQFOwyAKNqS4m/7JCsbuH4gQkPgPF561BHNL9oKfYgJq" \ "9P4kEFfDTBoXKBMxwWtT7AKV8dYvCa3vYzPQ/1BnqQdw2zECQQDyscdgR9Ih59PQ" \ "b72ddibdsxS65uXS2vzYLe7SKl+4R5JgJzw0M6DTAnoYFf6JAsKGZM15PCC0E16t" \ "RRo47U9VAkEAwjEVrlQ0/8yPACbDggDJg/Zz/uRu1wK0zjqj4vKjleubaX4SEvj7" \ "r6xxZm9hC1pMJAC9y3bbkbgCRBjXfyY6fQJBANe5aq2MaZ41wTOPf45NjbKXEiAo" \ "SbUpboKCIbyyaa8V/2h0t7D3C0dE9l4efsguqdZoF7Rh2/f1F70QpYRgfJkCQQCH" \ "oRrAeGXP50JVW72fNgeJGH/pnghgOa6of0JpxwhENJuGMZxUDfxTtUA6yD3iXP3j" \ "A3WL/wbaHsfOYf9Y+g1NAkAGLhx67Ah+uBNK4Xvfz0YPGINX20m+CMsxAw7FOaNv" \ "IW2oWFfZCB4APkIis79Ql45AHpavwx5XodBMzZwJUvlL\n" \ "-----END RSA PRIVATE KEY-----\n" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; printf("*** invalid key preload test\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = BADKEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); status = dkim_privkey_load(dkim); assert(status == DKIM_STAT_NORESOURCE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test146.c000066400000000000000000000120201337314105200237260ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define BADKEY "-----BEGIN RSA PRIVATE KEY-----" \ "MIICXQIBAAKBgQC4GUGr*d/6SFNzVLYpphnRd0QPGKz2uWnV65RAxa1Pw352Bqiz" \ "qiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFgF0gu3UJbNnu3+cd8k/kiQj+q" \ "4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3Dyc079gSLtnSrgXb+gQIDAQAB" \ "AoGAemlI0opm1Kvs2T4VliH8/tvX5FXbBH8LEZQAUwVeFTB/UQlieXyCV39pIxZO" \ "0Sa50qm8YNL9rb5HTSZiHQFOwyAKNqS4m/7JCsbuH4gQkPgPF561BHNL9oKfYgJq" \ "9P4kEFfDTBoXKBMxwWtT7AKV8dYvCa3vYzPQ/1BnqQdw2zECQQDyscdgR9Ih59PQ" \ "b72ddibdsxS65uXS2vzYLe7SKl+4R5JgJzw0M6DTAnoYFf6JAsKGZM15PCC0E16t" \ "RRo47U9VAkEAwjEVrlQ0/8yPACbDggDJg/Zz/uRu1wK0zjqj4vKjleubaX4SEvj7" \ "r6xxZm9hC1pMJAC9y3bbkbgCRBjXfyY6fQJBANe5aq2MaZ41wTOPf45NjbKXEiAo" \ "SbUpboKCIbyyaa8V/2h0t7D3C0dE9l4efsguqdZoF7Rh2/f1F70QpYRgfJkCQQCH" \ "oRrAeGXP50JVW72fNgeJGH/pnghgOa6of0JpxwhENJuGMZxUDfxTtUA6yD3iXP3j" \ "A3WL/wbaHsfOYf9Y+g1NAkAGLhx67Ah+uBNK4Xvfz0YPGINX20m+CMsxAw7FOaNv" \ "IW2oWFfZCB4APkIis79Ql45AHpavwx5XodBMzZwJUvlL\n" \ "-----END RSA PRIVATE KEY-----\n" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** use of invalid key after load failure\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = BADKEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* preload test */ status = dkim_privkey_load(dkim); assert(status == DKIM_STAT_NORESOURCE); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_NORESOURCE); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_INVALID); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test147.c000066400000000000000000000110031337314105200237270ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; r=y; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=F/cSOK/4qujIeNhKcC1LjAMFS33ORcsRqoEfNO6g1WXMlK5LW/foFePbUyFbbEbhY\r\n\t 8RhU+7C4R914QI6WW+lYMh11p0z1BGu2HJ4HHOlBivi1DDfZgsRZrEJhBeMngNIN9+\r\n\t 8HbGhTSWWpOBn+jYtfvGJBGtbv3AjgVgNropc7DM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/simple rsa-sha1 signing with report request\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, "test147", NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* request reporting tag */ status = dkim_add_xtag(dkim, DKIM_REPORTTAG, DKIM_REPORTTAGVAL); assert(status == DKIM_STAT_OK); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test148.c000066400000000000000000000104161337314105200237370ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing subdomain with invalid i= SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing subdomain with invalid i=\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN2, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); #define XHEADER05 "From: Murray S. Kucherawy " status = dkim_header(dkim, XHEADER05, strlen(XHEADER05)); assert(status == DKIM_STAT_OK); (void) dkim_set_signer(dkim, "@" DOMAIN); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_INVALID); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_INVALID); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test149.c000066400000000000000000000171321337314105200237420ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=NiN+5WZz+O0jY\r\n\t+OH1mCVhv3zM+SrJ6i0wTrhoaDOawOTwW10dF/ZTaMdFmrjJkQfxQenKQN0hmxRNm0Q\r\n\tabHoiaaO1N5owKY0/cUV78U5Z05bNjGl9P9goSgNsLGukRgjb+ellUI8U97Xi9mFjOG\r\n\tWm1iJ2FIq31Bh1mybmvlveKA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying with missing end CRLF\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06) - 2); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_FIXCRLF; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06) - 2); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test15.c000066400000000000000000000111521337314105200236460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; l=343; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=RrR6zc3KAYHOj\r\n\tFdWv9JRXIYmvOSBRZ9kR3M4y/S0KqrsUKFycJq9NcbY8lHyAGoJVgKFxmXOhC3+RVjy\r\n\tLOKPPJGikY+mgLvHgAS+lBK5tuQBWXb+W2uSACVCk0KfTeQv+9RaAecyBeX1CpjQHnc\r\n\tSIKKfWhjY7GdLyyg1mIb3rN4=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/simple rsa-sha1 verifying with lengths plus extra data\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test150.c000066400000000000000000000074331337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; printf("*** relaxed/relaxed rsa-sha1 signing with small key (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = SMALLKEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_SIGGEN); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test151.c000066400000000000000000000133631337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define JOBID2 "testing2" #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; dkim_sigkey_t key; DKIM *dkim; DKIM *resign; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; key = KEY; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_RESIGN)) { printf("*** relaxed/simple rsa-sha1 dual signing with shared body SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha1 dual signing with shared body\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ /* test mode */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* restrict signed headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, dkim_should_signhdrs, sizeof(u_char **)); dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); resign = dkim_sign(lib, JOBID2, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(resign != NULL); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_resign(dkim, resign, TRUE); assert(status == DKIM_STAT_INVALID); status = dkim_resign(resign, dkim, TRUE); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(resign, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_INVALID); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_add_xtag(resign, "xtag", "xvalue"); assert(status == DKIM_STAT_OK); status = dkim_eom(resign, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_eom(resign, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(resign, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_INVALID); status = dkim_free(resign); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test152.c000066400000000000000000000113261337314105200237330ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; h=From:Subject;\r\n\tb=ZROo1yr1USMzkafTSZYD76oJeHNK6CccgAZtD0t/7lWmrj6WqxhSe00goRylK60+s\r\n\t DihLPzDDhCW2aQpx1BN/geTXuKetEUjQGzF9onEa2o8YERmPbheOTjEV1+UXfF2Nsf\r\n\t jvNr8aQo5t1wzpHfG2HW5oInsvFrgsNr+rmnow9o=" const char *libsignheaders[] = { "Received", "From", "To", "Date", "Subject", "Message-ID", NULL }; const char *msgsignheaders[] = { "from", "subject", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 signing with message-specifc header sign list\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, &libsignheaders, sizeof libsignheaders); status = dkim_signhdrs(dkim, msgsignheaders); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test153.c000066400000000000000000000072271337314105200237410ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=RqQ3gVSDB3xUQQKQh1vCFBqu306DAVbz776m3ZK0Kgs6FJwgjb7z9McilKmYludRt\r\n\t GAt3WADSvGkSKUNShTh0/yyww5a7dLllFBKERievrA6WovExPrKXte1/4Z/6TiRWtD\r\n\t ak0ef7bir2japcq0hxet3BKHOZYm0MDDskkOFecg=;" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { _Bool testkey; u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char buf[10240]; printf("*** simple/simple rsa-sha1 verifying with chunking, FIXCRLF, and \"b=...;\"\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags */ flags = DKIM_LIBFLAGS_FIXCRLF; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, "test153", NULL, &status); assert(dkim != NULL); memset(buf, '\0', sizeof buf); strlcat(buf, DKIM_SIGNHEADER ": ", sizeof buf); strlcat(buf, SIG2, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER02, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER03, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER04, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER05, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER06, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER07, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER08, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, HEADER09, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, CRLF, sizeof buf); strlcat(buf, BODY00, sizeof buf); strlcat(buf, BODY01, sizeof buf); strlcat(buf, BODY01A, sizeof buf); strlcat(buf, BODY01B, sizeof buf); strlcat(buf, BODY01C, sizeof buf); strlcat(buf, BODY01D, sizeof buf); strlcat(buf, BODY01E, sizeof buf); strlcat(buf, BODY02, sizeof buf); strlcat(buf, BODY03, sizeof buf); strlcat(buf, BODY04, sizeof buf); strlcat(buf, BODY03, sizeof buf); strlcat(buf, BODY03, sizeof buf); strlcat(buf, BODY05, sizeof buf); strlcat(buf, BODY03, sizeof buf); strlcat(buf, BODY03, sizeof buf); status = dkim_chunk(dkim, buf, strlen(buf)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, NULL, 0); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, &testkey); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test154.c000066400000000000000000000060161337314105200237350ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" #define PHONYHEADER "From : Malformed " /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 signing with a phony/extra From\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags */ flags = DKIM_LIBFLAGS_STRICTHDRS; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, PHONYHEADER, strlen(PHONYHEADER)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test155.c000066400000000000000000000123761337314105200237440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=2; a=rsa-sha1; c=relaxed/relaxed; d=sendmail.com; s=test;\r\n\tt=1172620939; !cd=example.com; bh=2jmj7l5rSw0yVb/vlWAYkK/YBwk=; l=0;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=FEK+lJkwviA+DkORcv/clDh7NMmLyGzGHCzuOPsbaoTLqepslXlzc71a2FzEZJ4KF\r\n\t 1m209ORGDUozr9BZvaZeXD/HqoIiDBSbR30XgWG+IU1fGKCfVBzOYKTOzgmS0PaE3S\r\n\t Tvknxdxp63DBprMF5QAEJkiMvfr8ZCsCUKI0oyNY=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int nsigs; int c; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_CONDITIONAL)) { printf("*** conditional signature verifying (good) SKIPPED\n"); dkim_close(lib); return 0; } printf("*** conditional signature verifying (good)\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); for (c = 0; c < nsigs; c++) { assert((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0); assert(dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH); } status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test156.c000066400000000000000000000122671337314105200237440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=2; a=rsa-sha1; c=relaxed/relaxed; d=sendmail.com; s=test;\r\n\tt=1172620939; !cd=example.com; bh=2jmj7l5rSw0yVb/vlWAYkK/YBwk=; l=0;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=FEK+lJkwviA+DkORcv/clDh7NMmLyGzGHCzuOPsbaoTLqepslXlzc71a2FzEZJ4KF\r\n\t 1m209ORGDUozr9BZvaZeXD/HqoIiDBSbR30XgWG+IU1fGKCfVBzOYKTOzgmS0PaE3S\r\n\t Tvknxdxp63DBprMF5QAEJkiMvfr8ZCsCUKI0oyNY=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int nsigs; int c; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_CONDITIONAL)) { printf("*** conditional signature verifying (bad) SKIPPED\n"); dkim_close(lib); return 0; } printf("*** conditional signature verifying (bad)\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); status = dkim_getsiglist(dkim, &sigs, &nsigs); for (c = 0; c < nsigs; c++) { assert((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0); assert(dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH); assert(dkim_sig_geterror(sigs[c]) == DKIM_SIGERROR_CONDITIONAL); } status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test157.c000066400000000000000000000132271337314105200237420ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=2; a=rsa-sha1; c=relaxed/relaxed; d=sendmail.com; s=test;\r\n\tt=1172620939; !cd=example.com; bh=2jmj7l5rSw0yVb/vlWAYkK/YBwk=; l=0;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=FEK+lJkwviA+DkORcv/clDh7NMmLyGzGHCzuOPsbaoTLqepslXlzc71a2FzEZJ4KF\r\n\t 1m209ORGDUozr9BZvaZeXD/HqoIiDBSbR30XgWG+IU1fGKCfVBzOYKTOzgmS0PaE3S\r\n\t Tvknxdxp63DBprMF5QAEJkiMvfr8ZCsCUKI0oyNY=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int nsigs; int c; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_CONDITIONAL)) { printf("*** conditional signature verifying (altered) SKIPPED\n"); dkim_close(lib); return 0; } printf("*** conditional signature verifying (altered)\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); /* status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); */ status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); status = dkim_getsiglist(dkim, &sigs, &nsigs); for (c = 0; c < nsigs; c++) { if (strcasecmp(dkim_sig_getdomain(sigs[c]), DOMAIN2) == 0) { /* sendmail.com */ assert((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0); assert(dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH); assert(dkim_sig_geterror(sigs[c]) == DKIM_SIGERROR_CONDITIONAL); } else { /* example.com */ assert((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0); assert(dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MISMATCH); assert(dkim_sig_geterror(sigs[c]) == DKIM_SIGERROR_BADSIG); } } status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test158.c000066400000000000000000000072351337314105200237450ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2018, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define ALPHABET "ABCDEFGHJKLMNOPQRSTUVWXYZ" #define SIG2 "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=FeVAiQ9IrlrcaqfMbPIL3SDhDGlX7iXWzBCmOQw1AeY=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=h9qDkEVSzsmD8VQ4pyLgbVPIK4lAQMzRO1O1JAhPCjO+XZUB2/QutR/eniyhDoQjh\r\n\t SomVcn+Y9oiUq9jaZwJwobuknGAO07ew1yDP0XxmCpHKX3KDPVnBSaDxwhJAuMOLJK\r\n\t RYnme5Pf5PkK0S+pviF/OzORqm69tHsvF3V2EqyY=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int outlen = 0; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/relaxed rsa-sha256 signing SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/relaxed rsa-sha256 signing\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); while (outlen < 1100) { status = dkim_body(dkim, ALPHABET, strlen(ALPHABET)); assert(status == DKIM_STAT_OK); outlen += strlen(ALPHABET); } status = dkim_body(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test16.c000066400000000000000000000110261337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=qylGDIlwT+HP/6iiL3+WPCykGTvQZ6imIMiK4gk1A6mLAmwIUnBJeZA4EU0LWxNbG\r\n\t VAfVM92lP3rQpdADzJyCBeSBllH1hXwS2SMwDCK025E6ZpYVVphVFEv+2IcC2U8mHP\r\n\t xuYj8nAD4bJNjCwdVpVCq3PngQy2B1+jUNKrbKHg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/relaxed rsa-sha256 signing SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/relaxed rsa-sha256 signing\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test17.c000066400000000000000000000110221337314105200236440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=hNRIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6Vu\r\n\t P0hDA4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8S\r\n\t jD475GchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test18.c000066400000000000000000000110221337314105200236450ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=KuqPrMp0cdKwSDSu1zZDkhXOHDp1TvoiNmD0zrX7F2zcjHChVKbCGm6/GUk1JaxGO\r\n\t KnLj+0kTv7ZHbBWRd2lSytEyCwBqeZ604a36uA+raND69PP0gkxTsZ2jxcXM4ZGXVm\r\n\t 8AeIip7tvKEnwnnw2yuRINjOp2QBDosPFJXrD3sM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/relaxed rsa-sha256 signing SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/relaxed rsa-sha256 signing\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test19.c000066400000000000000000000110161337314105200236510ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=SF8TeM0zlWmM/4+8VIHRDTGsj7XIfZ7uMlTPcxZT2JKDTacH/LpJbA8RP522ieWA2\r\n\t 0H8azsqLADlSRO1LCex/ZaDu/BkiKSmTnvBibbUIP8NBEA2j4hlvN/7qKJ+XqTvSb3\r\n\t EQ3vJNZ/Hfe4gehyZO2l0DsESI3mk/T5IxVUgT0I=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 signing SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 signing\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test20.c000066400000000000000000000107421337314105200236460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=qyl\r\n\tGDIlwT+HP/6iiL3+WPCykGTvQZ6imIMiK4gk1A6mLAmwIUnBJeZA4EU0LWxNbGVAfVM\r\n\t92lP3rQpdADzJyCBeSBllH1hXwS2SMwDCK025E6ZpYVVphVFEv+2IcC2U8mHPxuYj8n\r\n\tAD4bJNjCwdVpVCq3PngQy2B1+jUNKrbKHg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/relaxed rsa-sha256 verifying SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/relaxed rsa-sha256 verifying\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test21.c000066400000000000000000000107371337314105200236530ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test22.c000066400000000000000000000107371337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Q/F\r\n\taAnLFKGqgb0XsRw5/8MslfNcrVIV2WJ++ZbhWdYZnLcAM16SwiUbHzzDPMkkKON7Lti\r\n\txNRzKSZVCxUMvH4C7Sk+K6M7gAoPh3bpmMSJw0eRjkcF787dW9lcOkkD60RDtZ+DhCb\r\n\tBQhNkPIJORnhCzE1y6AD2HsSQWfq6M9H1s=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/relaxed rsa-sha256 verifying SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/relaxed rsa-sha256 verifying\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test23.c000066400000000000000000000107341337314105200236520ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test24.c000066400000000000000000000113631337314105200236520ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\tl=340; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=QFfh0AXsFY0q0xi4eBYFs7JkecpGRMU5lq5tU86VdcPLYyaM/rm4ZjGXH5i9vbKWI\r\n\t jeYHu6xrkKQMr2dg8kTywkr0voQkD2dEwH/DzDN7410c1VDxdV8kK4pQCMibFHq35y\r\n\t czhtJOA7EMBYOHqMNrHZKBw5QC/rjI5d2OSPWYfA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/relaxed rsa-sha256 signing with lengths SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/relaxed rsa-sha256 signing with lengths\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test25.c000066400000000000000000000113571337314105200236560ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\tl=343; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=biBmbeAM73MeIJsI0kPxb0ACyxxbyUffRgjBu9c9kq/eOEY8nyCwPm3lnZ1ikQV5h\r\n\t Nl8fNCkYOU4jJIXyzHqHYBu1ZSOsrWpaHLVIycWJadu04EdyJXW663I2m0mENOZ3Tc\r\n\t NZzXdr4ol7JVBIXtfGOfwqIyjZ+X1azsRLaf6SS0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing with lengths SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing with lengths\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test26.c000066400000000000000000000113571337314105200236570ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\tl=340; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=OkSP9/9KTuHkXzc0KLoRcc5AcW97SA3RLPHuxdbTlCHyJgsyqrqPkOM85AdMJuYmH\r\n\t UiE1k12ge/AULlnlsBNLLRzO9aOpPVx4rLLpssFpPd0bWP37Y7apy0kM2ZrZDrexEo\r\n\t zPIEyU7aOnbLt/OTNSpiFwh51YGcBdlAtBS6bGEg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/relaxed rsa-sha256 signing with lengths SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/relaxed rsa-sha256 signing with lengths\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test27.c000066400000000000000000000113531337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\tl=343; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=IruPS7pHJ23nRr3Bm+pzruYiUsC4QwioY3LyBJmMvPo0hsc/967Tnlw9Wj111PaUf\r\n\t CjDeSmxCMc0YraVicqvqMXu6rNLPIj+3/buVE3/wCWz2IAtnqJyB0eMhELiiIdP9Oa\r\n\t /zVMYRDt8WAMFjqe8T6HkHNXoM6U5tZIdUoZswto=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 signing with lengths SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 signing with lengths\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test28.c000066400000000000000000000114631337314105200236570ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\tl=340; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=QFfh0AXsFY0q0xi4eBYFs7JkecpGRMU5lq5tU86VdcPLYyaM/rm4ZjGXH5i9vbKWI\r\n\tjeYHu6xrkKQMr2dg8kTywkr0voQkD2dEwH/DzDN7410c1VDxdV8kK4pQCMibFHq35yc\r\n\tzhtJOA7EMBYOHqMNrHZKBw5QC/rjI5d2OSPWYfA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/relaxed rsa-sha256 verifying with lengths plus extra data SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/relaxed rsa-sha256 verifying with lengths plus extra data\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test29.c000066400000000000000000000114601337314105200236550ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\tl=343; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=biBmbeAM73MeIJsI0kPxb0ACyxxbyUffRgjBu9c9kq/eOEY8nyCwPm3lnZ1ikQV5h\r\n\tNl8fNCkYOU4jJIXyzHqHYBu1ZSOsrWpaHLVIycWJadu04EdyJXW663I2m0mENOZ3TcN\r\n\tZzXdr4ol7JVBIXtfGOfwqIyjZ+X1azsRLaf6SS0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with lengths plus extra data SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with lengths plus extra data\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test30.c000066400000000000000000000114561337314105200236520ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=QVUr2KBvm7/Q/ustiYzOlFMN9G8IMqBzUX81BdpjSDI=;\r\n\tl=340; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=OkSP9/9KTuHkXzc0KLoRcc5AcW97SA3RLPHuxdbTlCHyJgsyqrqPkOM85AdMJuYmH\r\n\tUiE1k12ge/AULlnlsBNLLRzO9aOpPVx4rLLpssFpPd0bWP37Y7apy0kM2ZrZDrexEoz\r\n\tPIEyU7aOnbLt/OTNSpiFwh51YGcBdlAtBS6bGEg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/relaxed rsa-sha256 verifying with lengths and extra data SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/relaxed rsa-sha256 verifying with lengths and extra data\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test31.c000066400000000000000000000114531337314105200236500ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\tl=343; h=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=IruPS7pHJ23nRr3Bm+pzruYiUsC4QwioY3LyBJmMvPo0hsc/967Tnlw9Wj111PaUf\r\n\tCjDeSmxCMc0YraVicqvqMXu6rNLPIj+3/buVE3/wCWz2IAtnqJyB0eMhELiiIdP9Oa/\r\n\tzVMYRDt8WAMFjqe8T6HkHNXoM6U5tZIdUoZswto=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying with lengths and extra data SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying with lengths and extra data\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test32.c000066400000000000000000000110151337314105200236430ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with header reordering SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with header reordering\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test33.c000066400000000000000000000111461337314105200236510ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=hNRIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6Vu\r\n\t P0hDA4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8S\r\n\t jD475GchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing with trailing spaces SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing with trailing spaces\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05 " ", strlen(HEADER05) + 1); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06 " ", strlen(HEADER06) + 2); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07 " ", strlen(HEADER07) + 1); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08 " ", strlen(HEADER08) + 2); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09 " ", strlen(HEADER09) + 1); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test34.c000066400000000000000000000110271337314105200236500ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with extra signature spaces SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with extra signature spaces\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test35.c000066400000000000000000000110551337314105200236520ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying with extra signature spaces (failure) SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying with extra signature spaces (failure)\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_BADSIG); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test36.c000066400000000000000000000110141337314105200236460ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=nosuchkey;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying against no such key SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying against no such key\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_NOKEY); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test37.c000066400000000000000000000110321337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939;\r\n\tbh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with signature re-wrapping SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with signature re-wrapping\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test38.c000066400000000000000000000110311337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with header unwrapping SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with header unwrapping\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04UNWRAP, strlen(HEADER04UNWRAP)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test39.c000066400000000000000000000110411337314105200236510ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with extra leading spaces SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with extra leading spaces\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07XLEADSP, strlen(HEADER07XLEADSP)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test40.c000066400000000000000000000110351337314105200236440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with no leading spaces SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with no leading spaces\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07NOLEADSP, strlen(HEADER07NOLEADSP)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test41.c000066400000000000000000000211201337314105200236410ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" #define V_VALUE "1" #define A_VALUE "rsa-sha256" #define C_VALUE "relaxed/simple" #define D_VALUE "example.com" #define S_VALUE "test" #define T_VALUE "1172620939" #define BH_VALUE "yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=" #define H_VALUE "Received:Received:Received:From:To:Date:Subject:Message-ID" #define B_VALUE "hNRIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475GchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" struct local_sig { const char * ls_domain; const char * ls_signalg; const char * ls_timestamp; const char * ls_canon; const char * ls_version; const char * ls_selector; const char * ls_bodyhash; const char * ls_hdrlist; const char * ls_signature; }; /* ** ALLOC_HANDLE -- allocate a local signature handle ** ** Parameters: ** ignored -- a (void *) which we don't need ** ** Return value: ** Pointer to a local signature handle. */ void * alloc_handle(void *ignored) { void *new; new = (void *) malloc(sizeof(struct local_sig)); assert(new != NULL); memset(new, '\0', sizeof(struct local_sig)); return new; } /* ** TAGVALUES -- process a tag/value pair given a DKIM_SIG handle ** ** Parameters: ** user -- (void *) referring to a struct local_sig ** pcode -- parameter code being reported (DKIM_PARAM_*) ** param -- pointer to the text form of the tag ** value -- pointer to the text form of the value ** ** Return value: ** None. */ void tagvalues(void *user, dkim_param_t pcode, const u_char *param, const u_char *value) { struct local_sig *ls = (struct local_sig *) user; switch (pcode) { case DKIM_PARAM_DOMAIN: ls->ls_domain = value; break; case DKIM_PARAM_SIGNATURE: ls->ls_signature = value; break; case DKIM_PARAM_HDRLIST: ls->ls_hdrlist = value; break; case DKIM_PARAM_BODYHASH: ls->ls_bodyhash = value; break; case DKIM_PARAM_SELECTOR: ls->ls_selector = value; break; case DKIM_PARAM_VERSION: ls->ls_version = value; break; case DKIM_PARAM_CANONALG: ls->ls_canon = value; break; case DKIM_PARAM_TIMESTAMP: ls->ls_timestamp = value; break; case DKIM_PARAM_SIGNALG: ls->ls_signalg = value; break; case DKIM_PARAM_UNKNOWN: assert(0); } } /* ** PRESCREEN -- verify the contents of a local_sig structure ** ** Parameters: ** dkim -- DKIM handle ** sigs -- array of DKIM_SIGINFO pointers ** nsigs -- how many sigs there were ** ** Return value: ** DKIM_CBSTAT_CONTINUE (assuming no assertions fire). */ DKIM_CBSTAT prescreen(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs) { struct local_sig *ls; DKIM_SIGINFO *siginfo; assert(dkim != NULL); assert(sigs != NULL); assert(nsigs == 1); siginfo = sigs[0]; assert(siginfo != NULL); ls = dkim_sig_getcontext(siginfo); assert(ls != NULL); assert(ls->ls_signalg != NULL && strcmp(ls->ls_signalg, A_VALUE) == 0); assert(ls->ls_timestamp != NULL && strcmp(ls->ls_signalg, A_VALUE) == 0); assert(ls->ls_canon != NULL && strcmp(ls->ls_canon, C_VALUE) == 0); assert(ls->ls_version != NULL && strcmp(ls->ls_version, V_VALUE) == 0); assert(ls->ls_selector != NULL && strcmp(ls->ls_selector, S_VALUE) == 0); assert(ls->ls_bodyhash != NULL && strcmp(ls->ls_bodyhash, BH_VALUE) == 0); assert(ls->ls_hdrlist != NULL && strcmp(ls->ls_hdrlist, H_VALUE) == 0); assert(ls->ls_signature != NULL && strcmp(ls->ls_signature, B_VALUE) == 0); assert(ls->ls_domain != NULL && strcmp(ls->ls_domain, D_VALUE) == 0); return DKIM_CBSTAT_CONTINUE; } /* ** FREE_HANDLE -- deallocate a local signature handle ** ** Parameters: ** ignored -- a (void *) which we don't need ** handle -- pointer to the struct local_sig to be deallocated ** ** Return value: ** None. */ void free_handle(void *ignored, void *handle) { assert(handle != NULL); free(handle); } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signature decomposition callbacks SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signature decomposition callbacks\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) dkim_set_signature_handle(lib, alloc_handle); (void) dkim_set_signature_handle_free(lib, free_handle); (void) dkim_set_signature_tagvalues(lib, tagvalues); (void) dkim_set_prescreen(lib, prescreen); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test42.c000066400000000000000000000125301337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" int kl; /* ** KEY_LOOKUP -- key lookup ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** buf -- where to write the result ** buflen -- how much space is available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT key_lookup(DKIM *dkim, DKIM_SIGINFO *sig, unsigned char *buf, size_t buflen) { const char *selector; const char *domain; assert(dkim != NULL); assert(sig != NULL); assert(buf != NULL); selector = dkim_sig_getselector(sig); assert(selector != NULL); assert(strcmp(selector, SELECTOR) == 0); domain = dkim_sig_getdomain(sig); assert(domain != NULL); assert(strcmp(domain, DOMAIN) == 0); memset(buf, '\0', buflen); strncpy(buf, PUBLICKEY, buflen); kl = 1; return DKIM_STAT_OK; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; unsigned char hdr[MAXHEADER + 1]; kl = 0; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying with key callback SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying with key callback\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) dkim_set_key_lookup(lib, key_lookup); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); assert(kl == 1); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test43.c000066400000000000000000000114221337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with extra headers SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with extra headers\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); #define XHEADER1 "X-ExtraHeader-1: value1" #define XHEADER2 "X-ExtraHeader-2: value2" status = dkim_header(dkim, XHEADER1, strlen(XHEADER1)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, XHEADER2, strlen(XHEADER2)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test44.c000066400000000000000000000116251337314105200236550ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=hNRIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6Vu\r\n\t P0hDA4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8S\r\n\t jD475GchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" #define SKIPHEADER "Return-Path: " char *skipheaders[] = { "Return-Path", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing with header omission SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing with header omission\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* arrange to skip headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SKIPHDRS, skipheaders, sizeof(char **)); status = dkim_header(dkim, SKIPHEADER, strlen(SKIPHEADER)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test45.c000066400000000000000000000200061337314105200236470ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi81=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" struct local_sig { const char * ls_domain; const char * ls_signalg; const char * ls_timestamp; const char * ls_canon; const char * ls_version; const char * ls_selector; const char * ls_bodyhash; const char * ls_hdrlist; const char * ls_signature; }; /* ** ALLOC_HANDLE -- allocate a local signature handle ** ** Parameters: ** ignored -- a (void *) which we don't need ** ** Return value: ** Pointer to a local signature handle. */ void * alloc_handle(void *ignored) { void *new; new = (void *) malloc(sizeof(struct local_sig)); assert(new != NULL); memset(new, '\0', sizeof(struct local_sig)); return new; } /* ** TAGVALUES -- process a tag/value pair given a DKIM_SIG handle ** ** Parameters: ** user -- (void *) referring to a struct local_sig ** pcode -- parameter code being reported (DKIM_PARAM_*) ** param -- pointer to the text form of the tag ** value -- pointer to the text form of the value ** ** Return value: ** None. */ void tagvalues(void *user, dkim_param_t pcode, const u_char *param, const u_char *value) { struct local_sig *ls = (struct local_sig *) user; switch (pcode) { case DKIM_PARAM_DOMAIN: ls->ls_domain = value; break; case DKIM_PARAM_SIGNATURE: ls->ls_signature = value; break; case DKIM_PARAM_HDRLIST: ls->ls_hdrlist = value; break; case DKIM_PARAM_BODYHASH: ls->ls_bodyhash = value; break; case DKIM_PARAM_SELECTOR: ls->ls_selector = value; break; case DKIM_PARAM_VERSION: ls->ls_version = value; break; case DKIM_PARAM_CANONALG: ls->ls_canon = value; break; case DKIM_PARAM_TIMESTAMP: ls->ls_timestamp = value; break; case DKIM_PARAM_SIGNALG: ls->ls_signalg = value; break; case DKIM_PARAM_UNKNOWN: assert(0); } } /* ** PRESCREEN -- verify the contents of a local_sig structure ** ** Parameters: ** dkim -- DKIM handle ** sigs -- array of DKIM_SIGINFO pointers ** nsigs -- how many sigs there were ** ** Return value: ** DKIM_CBSTAT_CONTINUE (assuming no assertions fire). */ DKIM_CBSTAT prescreen(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs) { int c; struct local_sig *ls; assert(dkim != NULL); assert(sigs != NULL); assert(nsigs == 2); /* ** Arrange to skip the one that's simple/simple since we know ** it's bad for this test. */ for (c = 0; c < nsigs; c++) { ls = dkim_sig_getcontext(sigs[c]); if (strcasecmp(ls->ls_canon, "simple/simple") == 0) dkim_sig_ignore(sigs[c]); } return DKIM_CBSTAT_CONTINUE; } /* ** FREE_HANDLE -- deallocate a local signature handle ** ** Parameters: ** ignored -- a (void *) which we don't need ** handle -- pointer to the struct local_sig to be deallocated ** ** Return value: ** None. */ void free_handle(void *ignored, void *handle) { assert(handle != NULL); free(handle); } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signature selection SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signature selection\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) dkim_set_signature_handle(lib, alloc_handle); (void) dkim_set_signature_handle_free(lib, free_handle); (void) dkim_set_signature_tagvalues(lib, tagvalues); (void) dkim_set_prescreen(lib, prescreen); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test46.c000066400000000000000000000176671337314105200236730ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi81=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" struct local_sig { const char * ls_domain; const char * ls_signalg; const char * ls_timestamp; const char * ls_canon; const char * ls_version; const char * ls_selector; const char * ls_bodyhash; const char * ls_hdrlist; const char * ls_signature; }; /* ** ALLOC_HANDLE -- allocate a local signature handle ** ** Parameters: ** ignored -- a (void *) which we don't need ** ** Return value: ** Pointer to a local signature handle. */ void * alloc_handle(void *ignored) { void *new; new = (void *) malloc(sizeof(struct local_sig)); assert(new != NULL); memset(new, '\0', sizeof(struct local_sig)); return new; } /* ** TAGVALUES -- process a tag/value pair given a DKIM_SIG handle ** ** Parameters: ** user -- (void *) referring to a struct local_sig ** pcode -- parameter code being reported (DKIM_PARAM_*) ** param -- pointer to the text form of the tag ** value -- pointer to the text form of the value ** ** Return value: ** None. */ void tagvalues(void *user, dkim_param_t pcode, const u_char *param, const u_char *value) { struct local_sig *ls = (struct local_sig *) user; switch (pcode) { case DKIM_PARAM_DOMAIN: ls->ls_domain = value; break; case DKIM_PARAM_SIGNATURE: ls->ls_signature = value; break; case DKIM_PARAM_HDRLIST: ls->ls_hdrlist = value; break; case DKIM_PARAM_BODYHASH: ls->ls_bodyhash = value; break; case DKIM_PARAM_SELECTOR: ls->ls_selector = value; break; case DKIM_PARAM_VERSION: ls->ls_version = value; break; case DKIM_PARAM_CANONALG: ls->ls_canon = value; break; case DKIM_PARAM_TIMESTAMP: ls->ls_timestamp = value; break; case DKIM_PARAM_SIGNALG: ls->ls_signalg = value; break; case DKIM_PARAM_UNKNOWN: assert(0); } } /* ** PRESCREEN -- verify the contents of a local_sig structure ** ** Parameters: ** dkim -- DKIM handle ** sigs -- array of DKIM_SIGINFO pointers ** nsigs -- how many sigs there were ** ** Return value: ** DKIM_CBSTAT_CONTINUE (assuming no assertions fire). */ DKIM_CBSTAT prescreen(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs) { DKIM_SIGINFO *siginfo; assert(dkim != NULL); assert(sigs != NULL); assert(nsigs == 2); /* ** Arrange to swap order since we know for this test that the second ** one is good and the first one is bad. */ siginfo = sigs[1]; sigs[1] = sigs[0]; sigs[0] = siginfo; return DKIM_CBSTAT_CONTINUE; } /* ** FREE_HANDLE -- deallocate a local signature handle ** ** Parameters: ** ignored -- a (void *) which we don't need ** handle -- pointer to the struct local_sig to be deallocated ** ** Return value: ** None. */ void free_handle(void *ignored, void *handle) { assert(handle != NULL); free(handle); } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signature reordering SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signature reordering\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) dkim_set_signature_handle(lib, alloc_handle); (void) dkim_set_signature_handle_free(lib, free_handle); (void) dkim_set_signature_tagvalues(lib, tagvalues); (void) dkim_set_prescreen(lib, prescreen); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test47.c000066400000000000000000000113221337314105200236520ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 char *over_sign[] = { "Cc", NULL }; #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID:Cc;\r\n\tb=AX9mksH+hDJ1UpZWbfKSLmErwcELCieKzn7eix6Af4iSj08EtnAkRaT1lIBPPJQdJ\r\n\t rJ5UDOTHQ3xxNiHpsWJscYpmbqiNaSldpG37kPS8uKuJLSRIZbkoHKP9xlI9tUe6YF\r\n\t j7UWDc53jqeUX2Ei19d0mzMQUOuyYBue3+oJDXqc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing absent headers SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing absent headers\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_OVERSIGNHDRS, &over_sign, sizeof (char **)); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test48.c000066400000000000000000000110631337314105200236550ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with signed header missing (failure) SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with signed header missing (failure)\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); /* status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); */ status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_BADSIG); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test49.c000066400000000000000000000042531337314105200236610ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include /* libdb includes */ #ifdef QUERY_CACHE # include #endif /* QUERY_CACHE */ #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "../dkim-cache.h" #include "t-testdata.h" #define BUFRSZ 1024 #define QUERY "Test Key" #define DATA "Cached Data" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifndef QUERY_CACHE printf("*** query caching SKIPPED\n"); #else /* ! QUERY_CACHE */ int status; int err; u_int s1, s2, s3, s4; size_t buflen; DB *cache; char buf[BUFRSZ + 1]; printf("*** query caching\n"); cache = dkim_cache_init(NULL, NULL); err = 0; printf("--- empty cache\n"); buflen = sizeof buf; status = dkim_cache_query(cache, QUERY, 0, buf, &buflen, &err); assert(err == 0); assert(status == 1); printf("--- insert record\n"); status = dkim_cache_insert(cache, QUERY, DATA, 3, &err); assert(err == 0); assert(status == 0); printf("--- retrieve record\n"); memset(buf, '\0', sizeof buf); buflen = sizeof buf; status = dkim_cache_query(cache, QUERY, 0, buf, &buflen, &err); assert(err == 0); assert(status == 0); assert(buflen == strlen(DATA)); assert(strcmp(buf, DATA) == 0); printf("--- [pause for record to expire]\n"); sleep(4); printf("--- retrieve expired record\n"); buflen = sizeof buf; status = dkim_cache_query(cache, QUERY, 0, buf, &buflen, &err); assert(err == 0); assert(status == 1); printf("--- expire old records\n"); status = dkim_cache_expire(cache, 3, &err); assert(err == 0); assert(status == 1); printf("--- retrieve cache stats\n"); dkim_cache_stats(cache, &s1, &s2, &s3, &s4, FALSE); assert(s1 == 3); assert(s2 == 1); assert(s3 == 1); assert(s4 == 0); dkim_cache_close(cache); #endif /* ! QUERY_CACHE */ return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test50.c000066400000000000000000000110651337314105200236500ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; x=1172620999; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=J5C1QsfUQsFoWCqzH9M3WrJ8CiCTUDhTyRVKbGHBl0cEHLsQupH3UbZNkitEp07q+\r\n\t 6SpyHteqGZXDgRhhdJ7Q89jUX6ciJg+2qAh1YcUVKl628uZIW130q6ViZa2hNQ6OjZ\r\n\t QZSVJSrrEkZEIgFw7JL3Lm9wYCHCK8/Ib+SJkeSE=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; uint64_t sigttl; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** simple/simple rsa-sha1 signing with expiration times\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* set expiration time */ sigttl = 60; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNATURETTL, &sigttl, sizeof sigttl); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test51.c000066400000000000000000000062711337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; s=brisbane; d=example.com;\r\n" \ " c=simple/simple; q=dns/txt; i=joe@football.example.com;\r\n" \ " h=Received : From : To : Subject : Date : Message-ID;\r\n" \ " bh=2jUSOH9NhtVGCQWNr9BrIAPreKQjO6Sn7XIkfJVOzv8=;\r\n" \ " b=AuUoFEfDxTDkHlLXSZEpZj79LICEps6eda7W3deTVFOk4yAUoqOB\r\n" \ " 4nujc7YopdG5dWLSdNg6xNAZpOPr+kHxt1IrE+NahM6L/LbvaHut\r\n" \ " KVdkLLkpVaVVQPzeRDI009SO2Il5Lu7rDNH6mZckBdrIx0orEtZV\r\n" \ " 4bmp/YzhwvcubU4=;" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying published example SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying published example\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, THEADER00, strlen(THEADER00)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, THEADER01, strlen(THEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, THEADER02, strlen(THEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, THEADER03, strlen(THEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, THEADER04, strlen(THEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, THEADER05, strlen(THEADER05)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, TBODY, strlen(TBODY)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test52.c000066400000000000000000000120741337314105200236530ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tz=Received:=20received=20data=201|Received:=20received=20data=202|R\r\n\t eceived:=20received=20data=203=20part=201=0D=0A=09=20data=203=20pa\r\n\t rt=202|From:=20Murray=20S.=20Kucherawy=20|To:=20\r\n\t Sendmail=20Test=20Address=20|Date:=20Thu,=20\r\n\t 05=20May=202005=2011:59:09=20-0700|Subject:=20DKIM=20test=20messag\r\n\t e|Message-ID:=20<439094BF.5010709@sendmail.com>;\r\n\tb=WQRoaWuhpDyNLqyvUl/lZkHEzdAT5ncRDpkO18y66NjYQT4FVkKDaRkLet4utGK0q\r\n\t YkIW1z5Z6pbzqqXHmEuvc5FwCPe7RSJT20bcM/3JPCEIAfeLw6fqF9ZN8UMcEnjqbF\r\n\t RyuDEWnlRxSFf92ZxrkhqfsdityIQRtozhzl3DUI=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags = 0; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing with z-tags SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing with z-tags\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_ZTAGS); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test53.c000066400000000000000000000130101337314105200236430ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define MAXHDRCNT 64 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; z=Rec\r\n\teived:=20received=20data=201|Received:=20received=20data=202|Receiv\r\n\ted:=20received=20data=203=20part=201=0D=0A=09=20data=203=20part=202\r\n\t|From:=20Murray=20S.=20Kucherawy=20|To:=20Sendmai\r\n\tl=20Test=20Address=20|Date:=20Thu,=2005=20May\r\n\t=202005=2011:59:09=20-0700|Subject:=20DKIM=20test=20message|Message\r\n\t-ID:=20<439094BF.5010709@sendmail.com>; b=UfBRGUZXr6mCdxVNeavejTTWd\r\n\tWwZWarsUi90kj6K7AJWy4IWhYDpLPCt5tEYIQa4A6B/SkXHremA1QORVn8SW+7Z9xP4\r\n\tLNReV78biYbUnlncfHrEL3K7G3rR5bpa3bfNhdtGSVItLAg/f2XjHqiOQztjz1i4C/p\r\n\tD/pBm8XSWzlA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nhdrs; int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char *ohdrs[MAXHDRCNT]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with z-tags SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with z-tags\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(sigs != NULL); assert(sigs[0] != NULL); assert(nsigs == 1); nhdrs = MAXHDRCNT; status = dkim_ohdrs(dkim, sigs[0], ohdrs, &nhdrs); assert(status == DKIM_STAT_OK); assert(nhdrs == 8); assert(strcmp(ohdrs[0], HEADER02) == 0); assert(strcmp(ohdrs[1], HEADER03) == 0); assert(strcmp(ohdrs[2], HEADER04) == 0); assert(strcmp(ohdrs[3], HEADER05) == 0); assert(strcmp(ohdrs[4], HEADER06) == 0); assert(strcmp(ohdrs[5], HEADER07) == 0); assert(strcmp(ohdrs[6], HEADER08) == 0); assert(strcmp(ohdrs[7], HEADER09) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test54.c000066400000000000000000000123361337314105200236560ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=hNRIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6Vu\r\n\t P0hDA4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8S\r\n\t jD475GchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" #define SKIPHEADER "Return-Path: " char *signheaders[] = { "Received", "From", "To", "Date", "Subject", "Message-ID", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing with header selection SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing with header selection\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* arrange to sign specific headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, signheaders, sizeof(char **)); status = dkim_header(dkim, SKIPHEADER, strlen(SKIPHEADER)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); #define XHEADER1 "X-ExtraHeader-1: value1" #define XHEADER2 "X-ExtraHeader-2: value2" status = dkim_header(dkim, XHEADER1, strlen(XHEADER1)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, XHEADER2, strlen(XHEADER2)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test55.c000066400000000000000000000075611337314105200236630ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define GIBBERISHLEN (sizeof(GIBBERISH) - 1) #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=TRy6u0KYixKENCPL95G1Y1uwclQ9rWthX6rFgE7gWb8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=aMDMwcz08Na0zYLrEZnUMBUipMh3blE+pWiBSvX+t2ynaDUGTqd27xuR5JddL9y1T\r\n\t 6h0LkUMIcijsPBWa1WWfKL23QceksV75Y1/Tt6gmVi3SdVAoJbbZImrOaAQ3YQAn64\r\n\t dp1vI0Z8gSashYlwy+7gtmVSLAj/fpcAF6yNDPuE=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { size_t wlen = LARGEBODYSIZE; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; unsigned char body[LARGEBODYSIZE]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing large bodies SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing large bodies\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); memset(body, '\0', sizeof body); while (wlen > GIBBERISHLEN) { strlcat(body, GIBBERISH, sizeof body); wlen -= GIBBERISHLEN; } status = dkim_body(dkim, body, strlen(body)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test56.c000066400000000000000000000073431337314105200236620ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define GIBBERISHLEN (sizeof(GIBBERISH) - 1) #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=TRy6u0KYixKENCPL95G1Y1uwclQ9rWthX6rFgE7gWb8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=aMD\r\n\tMwcz08Na0zYLrEZnUMBUipMh3blE+pWiBSvX+t2ynaDUGTqd27xuR5JddL9y1T6h0Lk\r\n\tUMIcijsPBWa1WWfKL23QceksV75Y1/Tt6gmVi3SdVAoJbbZImrOaAQ3YQAn64dp1vI0\r\n\tZ8gSashYlwy+7gtmVSLAj/fpcAF6yNDPuE=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { size_t wlen = LARGEBODYSIZE; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char body[LARGEBODYSIZE]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying large bodies SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying large bodies\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); memset(body, '\0', sizeof body); while (wlen > GIBBERISHLEN) { strlcat(body, GIBBERISH, sizeof body); wlen -= GIBBERISHLEN; } status = dkim_body(dkim, body, strlen(body)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test57.c000066400000000000000000000104051337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=TRy6u0KYixKENCPL95G1Y1uwclQ9rWthX6rFgE7gWb8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=aMDMwcz08Na0zYLrEZnUMBUipMh3blE+pWiBSvX+t2ynaDUGTqd27xuR5JddL9y1T\r\n\t 6h0LkUMIcijsPBWa1WWfKL23QceksV75Y1/Tt6gmVi3SdVAoJbbZImrOaAQ3YQAn64\r\n\t dp1vI0Z8gSashYlwy+7gtmVSLAj/fpcAF6yNDPuE=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int wlen = LARGEBODYSIZE; u_int remain; #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; u_char *start; u_char *end; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; struct timeval t; unsigned char hdr[MAXHEADER + 1]; unsigned char body[LARGEBODYSIZE]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing random chunk sizes SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing random chunk sizes\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); memset(body, '\0', sizeof body); while (wlen > strlen(GIBBERISH)) { strlcat(body, GIBBERISH, sizeof body); wlen -= strlen(GIBBERISH); } /* random-length chunks */ (void) gettimeofday(&t, NULL); srandom(t.tv_usec); start = body; remain = strlen(body); end = body + remain; while (start < end) { wlen = random() % sizeof body + 1; if (wlen > remain) wlen = remain; printf("%d... ", wlen); status = dkim_body(dkim, start, wlen); assert(status == DKIM_STAT_OK); start += wlen; remain -= wlen; } printf("done!\n"); status = dkim_body(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test58.c000066400000000000000000000047641337314105200236700ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define BADHEADER05 "From: msk-at-opendkim.org" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; printf("*** verifying malformed message\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, BADHEADER05, strlen(BADHEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test59.c000066400000000000000000000061171337314105200236630ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define FAKETMPDIR "/nosuchdir" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bad temp files (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags and options */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_TMPDIR, FAKETMPDIR, strlen(FAKETMPDIR)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_NORESOURCE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test60.c000066400000000000000000000110411337314105200236430ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=nofws/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nsigs; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bogus canonicalization\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(nsigs == 1); assert(dkim_sig_geterror(sigs[0]) == DKIM_SIGERROR_INVALID_HC); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test61.c000066400000000000000000000105231337314105200236500ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha0; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple verifying with bogus signature algorithm\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test62.c000066400000000000000000000106351337314105200236550ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_SIGINFO *sig; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple verifying with missing \"bh\" tag\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_MISSING_BH); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test63.c000066400000000000000000000061231337314105200236530ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying missing From: header\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_SYNTAX); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_INVALID); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test64.c000066400000000000000000000147561337314105200236670ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" struct malloc_track { size_t mt_size; void * mt_ptr; struct malloc_track * mt_next; }; unsigned int mtsize; unsigned int mtcount; struct malloc_track *mtstack; /* ** DEBUG_INIT -- initialize tracking malloc() wrapper ** ** Parameters: ** None. ** ** Return value: ** None. */ void debug_init(void) { mtstack = NULL; mtsize = 0; mtcount = 0; } /* ** DEBUG_MALLOC -- tracking malloc() wrapper ** ** Parameters: ** closure -- memory closure (not used) ** nbytes -- how many bytes to get ** ** Return value: ** Pointer to allocated memory. */ void * debug_malloc(void *closure, size_t nbytes) { struct malloc_track *new; void *ptr; assert(nbytes > 0); new = (void *) malloc(sizeof(struct malloc_track)); if (new == NULL) return NULL; ptr = (void *) malloc(nbytes); if (new == NULL) return NULL; new->mt_next = mtstack; new->mt_ptr = ptr; new->mt_size = nbytes; mtstack = new; mtsize++; mtcount++; return ptr; } /* ** DEBUG_FREE -- tracking wrapper for free() ** ** Parameters: ** closure -- memory closure (not used) ** ptr -- pointer to free ** ** Return value: ** None. */ void debug_free(void *closure, void *ptr) { struct malloc_track *mt; struct malloc_track *last; assert(ptr != NULL); assert(mtstack != NULL); mt = mtstack; last = NULL; while (mt != NULL) { if (mt->mt_ptr == ptr) { if (mt == mtstack) mtstack = mt->mt_next; else last->mt_next = mt->mt_next; free(mt); free(ptr); mtsize--; return; } last = mt; mt = mt->mt_next; } assert(0); } /* ** DEBUG_DUMP -- return contents of malloc tracking ** ** Parameters: ** out -- stream to which to write ** ** Return value: ** None. */ void debug_dump(FILE *out) { struct malloc_track *mt; assert(out != NULL); fprintf(out, "--- %u allocation(s) recorded\n", mtcount); if (mtstack != NULL) { fprintf(out, "--- %u dangling allocation(s):\n", mtsize); mt = mtstack; while (mt != NULL) { fprintf(out, "\t%p %lu\n", mt->mt_ptr, (unsigned long) mt->mt_size); mt = mt->mt_next; } } } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with leak detection\n"); debug_init(); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(debug_malloc, debug_free); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); debug_dump(stdout); assert(mtsize == 0); assert(mtstack == NULL); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test65.c000066400000000000000000000150361337314105200236600ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" struct malloc_track { size_t mt_size; void * mt_ptr; struct malloc_track * mt_next; }; unsigned int mtsize; unsigned int mtcount; struct malloc_track *mtstack; /* ** DEBUG_INIT -- initialize tracking malloc() wrapper ** ** Parameters: ** None. ** ** Return value: ** None. */ void debug_init(void) { mtstack = NULL; mtsize = 0; mtcount = 0; } /* ** DEBUG_MALLOC -- tracking malloc() wrapper ** ** Parameters: ** closure -- memory closure (not used) ** nbytes -- how many bytes to get ** ** Return value: ** Pointer to allocated memory. */ void * debug_malloc(void *closure, size_t nbytes) { struct malloc_track *new; void *ptr; assert(nbytes > 0); new = (void *) malloc(sizeof(struct malloc_track)); if (new == NULL) return NULL; ptr = (void *) malloc(nbytes); if (new == NULL) return NULL; new->mt_next = mtstack; new->mt_ptr = ptr; new->mt_size = nbytes; mtstack = new; mtsize++; mtcount++; return ptr; } /* ** DEBUG_FREE -- tracking wrapper for free() ** ** Parameters: ** closure -- memory closure (not used) ** ptr -- pointer to free ** ** Return value: ** None. */ void debug_free(void *closure, void *ptr) { struct malloc_track *mt; struct malloc_track *last; assert(ptr != NULL); assert(mtstack != NULL); mt = mtstack; last = NULL; while (mt != NULL) { if (mt->mt_ptr == ptr) { if (mt == mtstack) mtstack = mt->mt_next; else last->mt_next = mt->mt_next; free(mt); free(ptr); mtsize--; return; } last = mt; mt = mt->mt_next; } assert(0); } /* ** DEBUG_DUMP -- return contents of malloc tracking ** ** Parameters: ** out -- stream to which to write ** ** Return value: ** None. */ void debug_dump(FILE *out) { struct malloc_track *mt; assert(out != NULL); fprintf(out, "--- %u allocation(s) recorded\n", mtcount); if (mtstack != NULL) { fprintf(out, "--- %u dangling allocation(s):\n", mtsize); mt = mtstack; while (mt != NULL) { fprintf(out, "\t%p %lu\n", mt->mt_ptr, (unsigned long) mt->mt_size); mt = mt->mt_next; } } } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with leak detection\n"); debug_init(); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(debug_malloc, debug_free); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); debug_dump(stdout); assert(mtsize == 0); assert(mtstack == NULL); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test66.c000066400000000000000000000063231337314105200236600ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with bogus From:\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); #define ALTHEADER05 "From: Murray" status = dkim_header(dkim, ALTHEADER05, strlen(ALTHEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_SYNTAX); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_INVALID); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test67.c000066400000000000000000000141651337314105200236640ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=hNR\r\n\tIcA7ZG6mZL9GPr5E9rJPQBy0DNnPSNAqYmtpbHJjhzWj3fsUKXDCEl8vJki6VuP0hDA\r\n\t4wRRJ6hkD0/u9iY2O+7xwAyuzkC3Z719CuGidnqlJt/1kJ4QW4KlcWJcj2v8SjD475G\r\n\tchVu0268Cz9PTJWSEqg/WZfWLQrji0gmy0=" /* ** FINAL -- final signature processing ** ** Parameters: ** dkim -- DKIM handle ** sigs -- array of DKIM_SIGINFO pointers ** nsigs -- how many sigs there were ** ** Return value: ** DKIM_CBSTAT_CONTINUE (assuming no assertions fire). */ DKIM_CBSTAT final(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs) { DKIM_STAT status; u_int flags; assert(sigs != NULL); assert(nsigs == 2); /* verify that the signatures are both okay */ status = dkim_sig_process(dkim, sigs[0]); assert(status == DKIM_STAT_OK); flags = dkim_sig_getflags(sigs[0]); assert((flags & DKIM_SIGFLAG_PROCESSED) != 0); assert((flags & DKIM_SIGFLAG_IGNORE) == 0); assert((flags & DKIM_SIGFLAG_PASSED) != 0); assert(dkim_sig_getbh(sigs[0]) == DKIM_SIGBH_MATCH); status = dkim_sig_process(dkim, sigs[1]); assert(status == DKIM_STAT_OK); flags = dkim_sig_getflags(sigs[1]); assert((flags & DKIM_SIGFLAG_PROCESSED) != 0); assert((flags & DKIM_SIGFLAG_IGNORE) == 0); assert((flags & DKIM_SIGFLAG_PASSED) != 0); assert(dkim_sig_getbh(sigs[1]) == DKIM_SIGBH_MATCH); return DKIM_CBSTAT_CONTINUE; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha1/rsa-256 verifying SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha1/rsa-256 verifying\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) dkim_set_final(lib, final); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test68.c000066400000000000000000000106421337314105200236610ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with altered body\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_BADSIG); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test69.c000066400000000000000000000105011337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with delayed processing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags */ flags = DKIM_LIBFLAGS_DELAYSIGPROC; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test70.c000066400000000000000000000145661337314105200236630ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define MAXHDRCNT 64 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; z=Rec\r\n\teived:=20received=20data=201|Received:=20received=20data=202|Receiv\r\n\ted:=20received=20data=203=20part=201=0D=0A=09=20data=203=20part=202\r\n\t|From:=20Murray=20S.=20Kucherawy=20|To:=20Sendmai\r\n\tl=20Test=20Address=20|Date:=20Thu,=2005=20May\r\n\t=202005=2011:59:09=20-0700|Subject:=20DKIM=20test=20message|Message\r\n\t-ID:=20<439094BF.5010709@sendmail.com>; b=UfBRGUZXr6mCdxVNeavejTTWd\r\n\tWwZWarsUi90kj6K7AJWy4IWhYDpLPCt5tEYIQa4A6B/SkXHremA1QORVn8SW+7Z9xP4\r\n\tLNReV78biYbUnlncfHrEL3K7G3rR5bpa3bfNhdtGSVItLAg/f2XjHqiOQztjz1i4C/p\r\n\tD/pBm8XSWzlA=" #define ALTHEADER02 "Received: received data 1 fghij" #define ALTHEADER03 "Received: received data 2 klmno" #define ALTHEADER04 "Received: received data 3 part 1\r\n\t data 3 part 2 pqrst" #define ALTHEADER05 "From: Murray S Kucherawy " /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int nhdrs; int nsigs; int ndiffs = 0; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO **sigs; struct dkim_hdrdiff *diffs = NULL; dkim_canon_t hc; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char *ohdrs[MAXHDRCNT]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_DIFFHEADERS) || !dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying with header diffing SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying with header diffing\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, ALTHEADER02, strlen(ALTHEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, ALTHEADER03, strlen(ALTHEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, ALTHEADER04, strlen(ALTHEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, ALTHEADER05, strlen(ALTHEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_BADSIG); status = dkim_getsiglist(dkim, &sigs, &nsigs); assert(status == DKIM_STAT_OK); assert(sigs != NULL); assert(sigs[0] != NULL); assert(nsigs == 1); nhdrs = MAXHDRCNT; status = dkim_sig_getcanons(sigs[0], &hc, NULL); assert(status == DKIM_STAT_OK); assert(hc == DKIM_CANON_RELAXED); status = dkim_ohdrs(dkim, sigs[0], ohdrs, &nhdrs); assert(status == DKIM_STAT_OK); assert(nhdrs == 8); assert(strcmp(ohdrs[0], HEADER02) == 0); assert(strcmp(ohdrs[1], HEADER03) == 0); assert(strcmp(ohdrs[2], HEADER04) == 0); assert(strcmp(ohdrs[3], HEADER05) == 0); assert(strcmp(ohdrs[4], HEADER06) == 0); assert(strcmp(ohdrs[5], HEADER07) == 0); assert(strcmp(ohdrs[6], HEADER08) == 0); assert(strcmp(ohdrs[7], HEADER09) == 0); assert(dkim_sig_getcanons(sigs[0], &hc, NULL) == DKIM_STAT_OK); status = dkim_diffheaders(dkim, hc, 5, (char **) ohdrs, nhdrs, &diffs, &ndiffs); assert(status == DKIM_STAT_OK); assert(ndiffs == 1); assert(strcmp(diffs[0].hd_old, ohdrs[3]) == 0); assert(strcmp(diffs[0].hd_new, ALTHEADER05) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test71.c000066400000000000000000000204741337314105200236570ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Cc:Message-ID;\r\n\tb=qo5Fy/OvM4nsRiazb81pxpjrUIhX0hHoXt3EchKVHklnI6vLKJPKRhChg6NCPcY20\r\n\t OVw8G0OqVhVxjUFb2By97EBJSECIjJabsvDsvjEfsrafj+f4H/FS1KauEBNNaP8KfN\r\n\t aLDkJzE2mKjcxoXBStRYq6iEsbyiAm57PVF4IoEQ=" #define XHDRNAME "Cc: " #define XHDRADDR "nosuchuser@nosuchdomain.com" #define XHDRVALEOL ",\r\n\t" #define XHDRVAL XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR XHDRVALEOL \ XHDRADDR #define XHEADERCC XHDRNAME XHDRVAL /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with large headers\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, XHEADERCC, strlen(XHEADERCC)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test72.c000066400000000000000000000123701337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define XHEADER "Cc: user@example.com" /* ** MESSAGE -- run the message's content ** ** Parameters: ** dkim -- DKIM handle ** hdr -- signature header content (may be NULL) ** hdrlen -- signature header size ** ** Return value: ** None. */ void message(DKIM *dkim, char *hdr) { int status; assert(dkim != NULL); if (hdr != NULL) { status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); } status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, XHEADER, strlen(XHEADER)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 signing with subsequent verifying SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 \"b=\" wrap test\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_SIMPLE, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); (void) message(dkim, NULL); snprintf(hdr, sizeof hdr, "%s: ", DKIM_SIGNHEADER); status = dkim_getsighdr(dkim, hdr + strlen(DKIM_SIGNHEADER) + 2, sizeof hdr - strlen(DKIM_SIGNHEADER) - 2, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); /* verify the message using the signature we just obtained */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) message(dkim, hdr); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test73.c000066400000000000000000000175371337314105200236670ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define BUFRSZ 1024 #define MAXADDRESS 256 #define MAXHEADER 4096 #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ #define SIG2 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; r=y; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=F/cSOK/4qujIeNhKcC1LjAMFS33ORcsRqoEfNO6g1WXMlK5LW/foFePbUyFbbEbhY\r\n\t 8RhU+7C4R914QI6WW+lYMh11p0z1BGu2HJ4HHOlBivi1DDfZgsRZrEJhBeMngNIN9+\r\n\t 8HbGhTSWWpOBn+jYtfvGJBGtbv3AjgVgNropc7DM=" size_t alen; unsigned char *abuf; unsigned char qbuf[BUFRSZ]; static int stub_dns_cancel(void *srv, void *q) { return DKIM_DNS_SUCCESS; } static int stub_dns_query(void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh) { abuf = buf; alen = buflen; strlcpy(qbuf, query, sizeof qbuf); return DKIM_DNS_SUCCESS; } static int stub_dns_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec) { unsigned char *cp; unsigned char *eom; int elen; int slen; int olen; char *q; unsigned char *len; unsigned char *dnptrs[3]; unsigned char **lastdnptr; HEADER newhdr; memset(&newhdr, '\0', sizeof newhdr); memset(&dnptrs, '\0', sizeof dnptrs); newhdr.qdcount = htons(1); newhdr.ancount = htons(1); newhdr.rcode = NOERROR; newhdr.opcode = QUERY; newhdr.qr = 1; newhdr.id = 0; lastdnptr = &dnptrs[2]; dnptrs[0] = abuf; /* copy out the new header */ memcpy(abuf, &newhdr, sizeof newhdr); cp = &abuf[HFIXEDSZ]; eom = &abuf[alen]; /* question section */ elen = dn_comp(qbuf, cp, eom - cp, dnptrs, lastdnptr); if (elen == -1) return DKIM_DNS_ERROR; cp += elen; PUTSHORT(T_TXT, cp); PUTSHORT(C_IN, cp); /* answer section */ elen = dn_comp(qbuf, cp, eom - cp, dnptrs, lastdnptr); if (elen == -1) return DKIM_DNS_ERROR; cp += elen; PUTSHORT(T_TXT, cp); PUTSHORT(C_IN, cp); PUTLONG(0L, cp); len = cp; cp += INT16SZ; slen = strlen(REPORTRECORD); q = REPORTRECORD; olen = 0; while (slen > 0) { elen = MIN(slen, 255); *cp = (char) elen; cp++; olen++; memcpy(cp, q, elen); q += elen; cp += elen; olen += elen; slen -= elen; } eom = cp; cp = len; PUTSHORT(olen, cp); *bytes = eom - abuf; if (dnssec != NULL) *dnssec = DKIM_DNSSEC_UNKNOWN; return DKIM_DNS_SUCCESS; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int hfd; int bfd; u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char addr[MAXADDRESS + 1]; unsigned char opts[BUFRSZ]; unsigned char smtp[BUFRSZ]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying with extra signature spaces and reportinfo (failure) SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying with extra signature spaces and reportinfo (failure)\n"); /* DNS stubs for the reporting data lookup */ dkim_dns_set_query_service(lib, NULL); dkim_dns_set_query_start(lib, stub_dns_query); dkim_dns_set_query_cancel(lib, stub_dns_cancel); dkim_dns_set_query_waitreply(lib, stub_dns_waitreply); /* set flags */ flags = DKIM_LIBFLAGS_TMPFILES; #ifdef TEST_KEEP_FILES flags |= DKIM_LIBFLAGS_KEEPFILES; #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_BADSIG); /* set up for the rest */ hfd = -1; bfd = -1; sig = dkim_getsignature(dkim); assert(sig != NULL); /* request report info, verify valid descriptors and address */ memset(addr, '\0', sizeof addr); memset(opts, '\0', sizeof opts); memset(smtp, '\0', sizeof smtp); status = dkim_sig_getreportinfo(dkim, sig, &hfd, &bfd, addr, sizeof addr, opts, sizeof opts, smtp, sizeof smtp, NULL); assert(status == DKIM_STAT_OK); assert(hfd > 2); assert(bfd > 2); assert(strcmp(addr, REPLYADDRESS) == 0); assert(strcmp(smtp, SMTPTOKEN) == 0); /* test descriptors */ status = lseek(hfd, 0, SEEK_CUR); assert(status >= 0); status = lseek(bfd, 0, SEEK_CUR); assert(status >= 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test74.c000066400000000000000000000144571337314105200236660ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha1; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=V+wiYd1cE70A40eDNUtYwU\r\n\tvqi727NN/vVo/OdC7jG4zvztIXCRjPKDXEfiZdW+6PZ08M4zA3GmLZI2p+IJTza+VDQ\r\n\tbohnvIUSRR6q9+Nddqz1qTCL0gNM5d64xKwrLUesk/3wb/Cvua6Atr+VBMFVCwQmSDf\r\n\trs4brLkqMyFOkCE=" #define SIG2 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" #define SIG3 "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=brisbane;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=Y3y\r\n\tVeA3WZdCZl1sGuOZNC3BBRhtGCOExkZdw5xQoGPvSX/q6AC1SAJvOUWOri95AZAUGs0\r\n\t/bIDzzt23ei9jc+rptlavrl/5ijMrl6ShmvkACk6It62KPkJcDpoGfi5AZkrfX1Ou/z\r\n\tqGg5xJX86Kqd7FgNolMg7PbfyWliK2Yb84=" int kl; /* ** KEY_LOOKUP -- key lookup ** ** Parameters: ** dkim -- DKIM handle ** sig -- DKIM_SIGINFO handle ** buf -- where to write the result ** buflen -- how much space is available at "buf" ** ** Return value: ** A DKIM_STAT_* constant. */ DKIM_STAT key_lookup(DKIM *dkim, DKIM_SIGINFO *sig, unsigned char *buf, size_t buflen) { const char *selector; const char *domain; assert(dkim != NULL); assert(sig != NULL); assert(buf != NULL); selector = dkim_sig_getselector(sig); assert(selector != NULL); assert(strcmp(selector, SELECTOR) == 0 || strcmp(selector, SELECTOR2) == 0); domain = dkim_sig_getdomain(sig); assert(domain != NULL); assert(strcmp(domain, DOMAIN) == 0); memset(buf, '\0', buflen); if (strcmp(selector, SELECTOR) == 0) strncpy(buf, PUBLICKEY, buflen); else strncpy(buf, PUBLICKEY2, buflen); kl++; return DKIM_STAT_OK; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; unsigned char hdr[MAXHEADER + 1]; kl = 0; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** simple/simple rsa-sha256 verifying with key callback and key reuse SKIPPED\n"); dkim_close(lib); return 0; } printf("*** simple/simple rsa-sha256 verifying with key callback and key reuse\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) dkim_set_key_lookup(lib, key_lookup); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG1); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG3); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); assert(kl == 2); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test75.c000066400000000000000000000062741337314105200236650ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=Gb2p2FRiCK0vAI+F5+EQ/l\r\n\tKrk9MdARHyw4noadY4R40VJrIrKgUtUL24frvN2NSf3kZaB1Edrksj/TYKsfzyPCUr/\r\n\tTTzf8Q/OWTEHAehsnUWZFK134WpidjMdn0kk1bNeVP7VWeQHgYh8eigji5pqbydusou\r\n\tMtlSHgKtSEKwi5o=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; time_t date; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_PARSE_TIME)) { printf("*** Date: value extraction SKIPPED\n"); return 0; } else { printf("*** Date: value extraction\n"); } #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); date = dkim_get_msgdate(dkim); assert(date == 1115319549); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test76.c000066400000000000000000000077701337314105200236700ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=1; a=rsa-sha1; c=relaxed/simple;" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 malformed signature\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_SYNTAX); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_NOSIG); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_NOSIG); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test77.c000066400000000000000000000110471337314105200236610ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; x=4472620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=mjX+KB5yZNsjL9LVeZFqEbQYTrjiQsVwQrJOQMHSiEjAP/a6IQIBpp7QOFfLhYugI\r\n\t j1eeii3JaBHsjBFvPYzd/OiL57j7SDDvg2/sJ6dL8TGyWDvBD5l/BmL5y7Nl4vmzrr\r\n\t 3Y63M3i5yJcP4gbCIdFXVP9qtmr4kktFwsZ9g9Tc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with oversized expiration\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 3300000000UL; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNATURETTL, &fixed_time, sizeof fixed_time); fixed_time = 1172620939UL; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test78.c000066400000000000000000000105351337314105200236630ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; x=4472620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=mjX\r\n\t+KB5yZNsjL9LVeZFqEbQYTrjiQsVwQrJOQMHSiEjAP/a6IQIBpp7QOFfLhYugIj1eei\r\n\ti3JaBHsjBFvPYzd/OiL57j7SDDvg2/sJ6dL8TGyWDvBD5l/BmL5y7Nl4vmzrr3Y63M3\r\n\ti5yJcP4gbCIdFXVP9qtmr4kktFwsZ9g9Tc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; dkim_query_t qtype = DKIM_QUERY_FILE; DKIM *dkim; DKIM_LIB *lib; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with oversized expiration\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test79.c000066400000000000000000000107151337314105200236640ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with space-laden header names\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); #define XHEADER07 "Date : Thu, 05 May 2005 11:59:09 -0700" status = dkim_header(dkim, XHEADER07, strlen(XHEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test80.c000066400000000000000000000106341337314105200236540ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; dkim_query_t qtype = DKIM_QUERY_FILE; DKIM *dkim; DKIM_LIB *lib; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with space-laden header names\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); #define XHEADER07 "Date : Thu, 05 May 2005 11:59:09 -0700" status = dkim_header(dkim, XHEADER07, strlen(XHEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test81.c000066400000000000000000000106701337314105200236550ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; i=@sub.example.com; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=UqAVa+pZsR6XYjPdx5oSoMCbgCCGyy6uD/AujlCKCuXVinpc298coDqyTWVyCxnht\r\n\t louW5n16cmQiyDVWt2b4V+ylalOGoS7Mv5mvXU59I9IMsrqqLss+zwozm3Sdq/9/3F\r\n\t 2uFPV4bZdMmuMihlml2/NNsfxgg+fKKbUIkZCWYY=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with i= set\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); (void) dkim_set_signer(dkim, "@sub." DOMAIN); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test82.c000066400000000000000000000105661337314105200236620ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; i=@sub.example.com; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID; b=UqA\r\n\tVa+pZsR6XYjPdx5oSoMCbgCCGyy6uD/AujlCKCuXVinpc298coDqyTWVyCxnhtlouW5\r\n\tn16cmQiyDVWt2b4V+ylalOGoS7Mv5mvXU59I9IMsrqqLss+zwozm3Sdq/9/3F2uFPV4\r\n\tbZdMmuMihlml2/NNsfxgg+fKKbUIkZCWYY=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with i=/d= mismatch and t=s in the key\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test83.c000066400000000000000000000113161337314105200236550ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=sendmail.com; s=test;\r\n\tt=1172620939; i=@eng.sendmail.com;\r\n\tbh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=TE4MmJAd1K2WvqOU1hlKCYJLsfCXvzObRYjAUdRk0PHwK17OyUnBh+i6jJkyzPOsf\r\n\t 5Fjspu2AfD5vh9CVTmnKCAQG6/FzXKNxHluXGJJBv5E3YQtUcQ6jOmA6wD2jTvjIEC\r\n\t M/wq57hPa8SH+118tog/ymOj4TRbFOiBVNBbN9/M=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing subdomain with i= SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing subdomain with i=\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN2, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); #define XHEADER05 "From: Murray S. Kucherawy " status = dkim_header(dkim, XHEADER05, strlen(XHEADER05)); assert(status == DKIM_STAT_OK); (void) dkim_set_signer(dkim, "@eng.sendmail.com"); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test84.c000066400000000000000000000124141337314105200236560ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define SIG1 "v=1; a=rsa-sha256; c=relaxed/simple; d=sendmail.com; s=test; t=1172620939; i=@eng.sendmail.com; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=; h=Received:Received:Received:From:To:Date:Subject:Message-ID; b=r5DyHh4oxZcCBcIzpKTnEk6yvWDI9g9DI+UUIwl2ZAcZ6P0BbsOQ8MEjmUdwlZitqoFLa25/Re8/rC5kHasOb3vs0T37vkasoTb1rGR7y/bcMnY4hRkPAyC7NoLoTjneJMTQ/WQYnZe3DJ8lVuDRYvY9BeV2EjH8kiGsa9QttiA=" #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=sendmail.com; s=test;\r\n\tt=1172620939; i=@eng.sendmail.com; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9\r\n\tn8qz5fgAycHi80=; h=Received:Received:Received:From:To:Date:Subject:\r\n\t Message-ID; b=r5DyHh4oxZcCBcIzpKTnEk6yvWDI9g9DI+UUIwl2ZAcZ6P0BbsOQ\r\n\t8MEjmUdwlZitqoFLa25/Re8/rC5kHasOb3vs0T37vkasoTb1rGR7y/bcMnY4hRkPAyC\r\n\t7NoLoTjneJMTQ/WQYnZe3DJ8lVuDRYvY9BeV2EjH8kiGsa9QttiA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int presult; DKIM_STAT status; dkim_query_t qtype = DKIM_QUERY_FILE; DKIM *dkim; DKIM_LIB *lib; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 verifying subdomain with i= SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 verifying subdomain with i=\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); #define XHEADER05 "From: Murray S. Kucherawy " status = dkim_header(dkim, XHEADER05, strlen(XHEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test85.c000066400000000000000000000112271337314105200236600ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha256; c=relaxed/simple; d=sendmail.com; s=test;\r\n\tt=1172620939; bh=yHBAX+3IwxTZIynBuB/5tlsBInJq9n8qz5fgAycHi80=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=HLU6+LztURsYvmqEEHX74Vx9dR7tRtUDIlgRws7WCk5D8HqHx9Z2sSWkPqlkbh+me\r\n\t XydZWexg42oxOE94p6BLa5rDhJopSvlHBeZeCLp0U+JIkk7TlLWv82K+2Tbykx1b8b\r\n\t YuriFafkyPYhm+SFHs0zirGDJz71dYnTMc229znM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { printf("*** relaxed/simple rsa-sha256 signing subdomain with i=/d= mismatch SKIPPED\n"); dkim_close(lib); return 0; } printf("*** relaxed/simple rsa-sha256 signing subdomain with i=/d= mismatch\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN2, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); #define XHEADER05 "From: Murray S. Kucherawy " status = dkim_header(dkim, XHEADER05, strlen(XHEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test86.c000066400000000000000000000056341337314105200236660ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define BADFROM "From: \"Foo \"BAR Baz\" " /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags = 0; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); printf("*** relaxed/simple check for proper From syntax\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ flags |= DKIM_LIBFLAGS_STRICTHDRS; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA256, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); /* arrange to sign specific headers */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, dkim_should_signhdrs, sizeof(char **)); status = dkim_header(dkim, BADFROM, strlen(BADFROM)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_SYNTAX); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test87.c000066400000000000000000000107151337314105200236630ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, 2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=%ld; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ int len; time_t now; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with far future timestamp\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); (void) time(&now); len = snprintf(hdr, sizeof hdr, "%s: ", DKIM_SIGNHEADER); snprintf(hdr + len, sizeof hdr - len, SIG2, (long) (now + 86400)); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test88.c000066400000000000000000000075641337314105200236740ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #define MAXHEADER 4096 #define MAXMSGSIZE 16384 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; unsigned char buf[MAXMSGSIZE]; printf("*** relaxed/simple rsa-sha1 verifying using chunking API (single chunk)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); memset(buf, '\0', sizeof buf); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); strlcpy(buf, hdr, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER01, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER02, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER03, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER04, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER05, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER06, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER07, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER08, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, HEADER09, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, CRLF, MAXMSGSIZE); strlcat(buf, BODY00, MAXMSGSIZE); strlcat(buf, BODY01, MAXMSGSIZE); strlcat(buf, BODY01A, MAXMSGSIZE); strlcat(buf, BODY01B, MAXMSGSIZE); strlcat(buf, BODY01C, MAXMSGSIZE); strlcat(buf, BODY01D, MAXMSGSIZE); strlcat(buf, BODY01E, MAXMSGSIZE); strlcat(buf, BODY02, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY04, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY05, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); strlcat(buf, BODY03, MAXMSGSIZE); status = dkim_chunk(dkim, buf, strlen(buf)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_chunk(dkim, NULL, 0); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test89.c000066400000000000000000000124711337314105200236660ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying using chunking API (many chunks)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_chunk(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, CRLF, strlen(CRLF)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_chunk(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_INVALID); status = dkim_chunk(dkim, NULL, 0); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test90.c000066400000000000000000000107561337314105200236620ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 signing with CRLF fixing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); /* set flags */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags = DKIM_LIBFLAGS_FIXCRLF; #ifdef TEST_KEEP_FILES flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY00, strlen(NBODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01, strlen(NBODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01A, strlen(NBODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01B, strlen(NBODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01C, strlen(NBODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01D, strlen(NBODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01E, strlen(NBODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY02, strlen(NBODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY04, strlen(NBODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY05, strlen(NBODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test91.c000066400000000000000000000111231337314105200236500ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Q4G/ki/5soDXGxs43JfV+qEKDr5X3GgTDNeZqWL3zLLC5DXWWzmnKRcU8NH4Wsfkh\r\n\t o5tMo4NRmqnB2eZtozsyXdHo2ekUPLxuAQJomM4JHaPTfsraHwkibQIkPpW5hf/Rc2\r\n\t 0QgP48iQBjxqcOSn/Vwk5QDup4Qj1vgOxBqTqwdg=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with CRLF fixing\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_FIXCRLF; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY00, strlen(NBODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01, strlen(NBODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01A, strlen(NBODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01B, strlen(NBODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01C, strlen(NBODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01D, strlen(NBODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY01E, strlen(NBODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY02, strlen(NBODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY04, strlen(NBODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY05, strlen(NBODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, NBODY03, strlen(NBODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test92.c000066400000000000000000000111051337314105200236510ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID:\r\n\t Subject:Cc:Bcc;\r\n\tb=nQiEx5HFKJYNlMuy0TOjxOol/P19rPjPr/wluVkvYfW9NoUp+uz1fsReg0AIEvlkc\r\n\t glXxG+VY4WqDj7nd9sB+PtJWj7RsTiAXhAVkAG1Y6vULjokbyQMA7Sb/OHFn30573g\r\n\t x1MNi2OnPZKtLHqxhk3KyrvjazmUQKWttbjalc+c=" char *extra_hdrs[] = { "Subject", "Cc", "Bcc", NULL }; /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 signing with extra headers\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_OVERSIGNHDRS, &extra_hdrs, sizeof (char **)); dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_SIMPLE, DKIM_SIGN_RSASHA1, -1L, &status); assert(dkim != NULL); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test93.c000066400000000000000000000105371337314105200236620ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID:Cc:Bcc; b=eOU+Un/1oD413jr\r\n\txu9pya11G15GHtDGFQqg+NItchNwXm8fCNWAfmrY8DOuYEOpD2RU5GeqAQcOzJF8mqz\r\n\tjscbi84g/HR5SMjfCemqNvUtOj0vB/G3CSRE5rCaZe3DZJAuG7wqhuDuQi/3FjSS/gL\r\n\tAjGORLp7utw/8JZdasiKkc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with extra (but missing) headers\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test94.c000066400000000000000000000107001337314105200236530ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID:Cc:Bcc; b=eOU+Un/1oD413jr\r\n\txu9pya11G15GHtDGFQqg+NItchNwXm8fCNWAfmrY8DOuYEOpD2RU5GeqAQcOzJF8mqz\r\n\tjscbi84g/HR5SMjfCemqNvUtOj0vB/G3CSRE5rCaZe3DZJAuG7wqhuDuQi/3FjSS/gL\r\n\tAjGORLp7utw/8JZdasiKkc=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with extra headers added (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER10, strlen(HEADER10)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_BADSIG); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test95.c000066400000000000000000000170111337314105200236560ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG "v=2; a=rsa-sha1; c=relaxed/relaxed; d=sendmail.com; s=test;\r\n\tt=1172620939; !cd=example.com; bh=2jmj7l5rSw0yVb/vlWAYkK/YBwk=; l=0;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=FEK+lJkwviA+DkORcv/clDh7NMmLyGzGHCzuOPsbaoTLqepslXlzc71a2FzEZJ4KF\r\n\t 1m209ORGDUozr9BZvaZeXD/HqoIiDBSbR30XgWG+IU1fGKCfVBzOYKTOzgmS0PaE3S\r\n\t Tvknxdxp63DBprMF5QAEJkiMvfr8ZCsCUKI0oyNY=" #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=;\r\n\th=Received:Received:Received:From:To:Date:Subject:Message-ID;\r\n\tb=Jf+j2RDZRkpIF1KaL5ByhHFPWj5RMeX5764IVlwIc11equjQND51K9FfL5pyjXvwj\r\n\t FoFPW0PGJb3liej6iDDEHgYpXR4p5qqlGx/C1Q9gf/MQN/Xlkv6ZXgR38QnWAfZxh5\r\n\t N1f5xUg+SJb5yBDoXklG62IRdia1Hq9MuiGumrGM=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; uint64_t fixed_time; DKIM *dkim; DKIM *dkim2; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); if (!dkim_libfeature(lib, DKIM_FEATURE_CONDITIONAL)) { printf("*** conditional signature generation SKIPPED\n"); dkim_close(lib); return 0; } printf("*** conditional signature generation\n"); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ key = KEY; dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, -1L, &status); dkim2 = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN2, DKIM_CANON_RELAXED, DKIM_CANON_RELAXED, DKIM_SIGN_RSASHA1, 0L, &status); assert(dkim != NULL); status = dkim_conditional(dkim2, DOMAIN); assert(status == DKIM_STAT_OK); /* fix signing time */ fixed_time = 1172620939; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixed_time, sizeof fixed_time); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim2, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim2); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim2, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim2, NULL); assert(status == DKIM_STAT_OK); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG2, hdr) == 0); memset(hdr, '\0', sizeof hdr); status = dkim_getsighdr(dkim2, hdr, sizeof hdr, strlen(DKIM_SIGNHEADER) + 2); assert(status == DKIM_STAT_OK); assert(strcmp(SIG, hdr) == 0); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); status = dkim_free(dkim2); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test96.c000066400000000000000000000106621337314105200236640ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=sendmail.com;\r\n\ts=brisbane; t=1172620939; i=msk@sendmail.com; bh=ll/0h2aWgG+D3ewmE4\r\n\tY3pY7Ukz8=; h=; b=k1ZKkMnlh62VdAwa3umwZf6yhF9TWF4PERI5OXKoxU2TAtvwNZ6Q\r\n\tLMlELWHEG0Q1OORyb4cpQPfgGdOc6m38r0o/+k4rvlwnWsejpMWJgd4mD4e6U0b+pEt\r\n\txO704bDKUlzV83MAqIN/QdxW5dvwOyr1/1OrVu2fTUlUp6SWaa2o=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_SIGINFO *sig; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying with empty h= (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_EMPTY_H); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test97.c000066400000000000000000000107211337314105200236610ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=sendmail.com;\r\n\ts=brisbane; t=1172620939; i=msk@sendmail.com; bh=ll/0h2aWgG+D3ewmE4\r\n\tY3pY7Ukz8=; h=subject:to:date; b=k1ZKkMnlh62VdAwa3umwZf6yhF9TWF4PERI5OXKoxU2TAtvwNZ6Q\r\n\tLMlELWHEG0Q1OORyb4cpQPfgGdOc6m38r0o/+k4rvlwnWsejpMWJgd4mD4e6U0b+pEt\r\n\txO704bDKUlzV83MAqIN/QdxW5dvwOyr1/1OrVu2fTUlUp6SWaa2o=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_SIGINFO *sig; DKIM_LIB *lib; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/simple rsa-sha1 verifying h= lacking required headers (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_INVALID_H); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test98.c000066400000000000000000000114071337314105200236640ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/relaxed; d=example.com; s=test;\r\n\tt=1172620939; bh=Z9ONHHsBrKN0pbfrOu025VfbdR4=; l=340; h=Received:\r\n\t Received:Received:From:To:Date:Subject:Message-ID; b=NiN+5WZz+O0jY\r\n\t+OH1mCVhv3zM+SrJ6i0wTrhoaDOawOTwW10dF/ZTaMdFmrjJkQfxQenKQN0hmxRNm0Q\r\n\tabHoiaaO1N5owKY0/cUV78U5Z05bNjGl9P9goSgNsLGukRgjb+ellUI8U97Xi9mFjOG\r\n\tWm1iJ2FIq31Bh1mybmvlveKA=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { u_int flags; DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** relaxed/relaxed rsa-sha1 verifying with oversized l= value (failure)\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); flags |= DKIM_LIBFLAGS_SIGNLEN; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); /* status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY06, strlen(BODY06)); assert(status == DKIM_STAT_OK); */ status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_CANTVRFY); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_geterror(sig) == DKIM_SIGERROR_TOOLARGE_L); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-test99.c000066400000000000000000000107641337314105200236720ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim-internal.h" #include "t-testdata.h" #define MAXHEADER 4096 #define SIG2 "v=1; a=rsa-sha1; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1172620939; bh=ll/0h2aWgG+D3ewmE4Y3pY7Ukz8=; h=Received:Received:\r\n\t Received:From:To:Date:Subject:Message-ID; b=bj9kVUbnBYfe9sVzH9lT45\r\n\tTFKO3eQnDbXLfgmgu/b5QgxcnhT9ojnV2IAM4KUO8+hOo5sDEu5Co/0GASH0vHpSV4P\r\n\t377Iwew3FxvLpHsVbVKgXzoKD4QSbHRpWNxyL6LypaaqFa96YqjXuYXr0vpb88hticn\r\n\t6I16//WThMz8fMU=" /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { #ifdef TEST_KEEP_FILES u_int flags; #endif /* TEST_KEEP_FILES */ DKIM_STAT status; DKIM *dkim; DKIM_LIB *lib; DKIM_SIGINFO *sig; dkim_query_t qtype = DKIM_QUERY_FILE; unsigned char hdr[MAXHEADER + 1]; printf("*** exercise dkim_sig_hdrsigned()\n"); #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); assert(lib != NULL); #ifdef TEST_KEEP_FILES /* set flags */ flags = (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); #endif /* TEST_KEEP_FILES */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); dkim = dkim_verify(lib, JOBID, NULL, &status); assert(dkim != NULL); snprintf(hdr, sizeof hdr, "%s: %s", DKIM_SIGNHEADER, SIG2); status = dkim_header(dkim, hdr, strlen(hdr)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER01, strlen(HEADER01)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); assert(status == DKIM_STAT_OK); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); assert(status == DKIM_STAT_OK); status = dkim_eoh(dkim); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY00, strlen(BODY00)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01, strlen(BODY01)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01A, strlen(BODY01A)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01B, strlen(BODY01B)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01C, strlen(BODY01C)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01D, strlen(BODY01D)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY01E, strlen(BODY01E)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY02, strlen(BODY02)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY04, strlen(BODY04)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY05, strlen(BODY05)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_body(dkim, BODY03, strlen(BODY03)); assert(status == DKIM_STAT_OK); status = dkim_eom(dkim, NULL); assert(status == DKIM_STAT_OK); sig = dkim_getsignature(dkim); assert(sig != NULL); assert(dkim_sig_hdrsigned(sig, "from") == TRUE); assert(dkim_sig_hdrsigned(sig, "content-type") == FALSE); status = dkim_free(dkim); assert(status == DKIM_STAT_OK); dkim_close(lib); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-testdata.h000066400000000000000000000173421337314105200243460ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ #define CRLF "\r\n" #define SP " " #define LARGEBODYSIZE 65536 #define LARGELINESIZE 4100 #define KEYFILE "/tmp/testkeys" #define JOBID "testing" #define SELECTOR "test" #define SELECTOR2 "brisbane" #define SELECTOR256 "sha256only" #define SELECTORBADH "badh" #define SELECTORBADK "badk" #define SELECTORBADV "badv" #define SELECTORNOK "nok" #define SELECTORNOP "nop" #define SELECTOREMPTYP "emptyp" #define SELECTORCORRUPTP "corruptp" #define DOMAIN "example.com" #define DOMAIN2 "sendmail.com" #define REPLYADDRESS "postmaster" #define SMTPTOKENENC "=5BDKIM=20error=5D" #define SMTPTOKEN "[DKIM error]" #define USER "msk" #define HEADER01 "Received: received data 0" #define HEADER02 "Received: received data 1" #define HEADER03 "Received: received data 2" #define HEADER04 "Received: received data 3 part 1\r\n\t data 3 part 2" #define HEADER04UNWRAP "Received: received data 3 part 1 data 3 part 2" #define HEADER05 "From: Murray S. Kucherawy " #define HEADER06 "To: Sendmail Test Address " #define HEADER07 "Date: Thu, 05 May 2005 11:59:09 -0700" #define HEADER07XLEADSP "Date: Thu, 05 May 2005 11:59:09 -0700" #define HEADER07NOLEADSP "Date:Thu, 05 May 2005 11:59:09 -0700" #define HEADER08 "Subject: DKIM test message" #define HEADER09 "Message-ID: <439094BF.5010709@sendmail.com>" #define HEADER10 "Cc: user@example.com" #define BODY00 "This is a message body. Fun!\r\n" #define BODY01 "Here is a second line.\r\n" #define BODY01A "Here is a line" #define BODY01B " that is broken up across calls.\r" #define BODY01C "\n" #define BODY01D "Now we can try something interesting, like a\r\nmulti-line buffer. This should not be mangled.\r\n" #define BODY01E "And a line with a trailing space: \r\n" #define BODY02 "Next we'll try a blank.\r\n" #define BODY03 "\r\n" #define BODY04 "Next we'll try multiple blanks.\r\n" #define BODY05 "Finally we'll try multiple trailing blanks.\r\n" #define BODY06 "Surprise, more data!\r\n" #define NBODY00 "This is a message body. Fun!\n" #define NBODY01 "Here is a second line.\r" #define NBODY01A "Here is a line" #define NBODY01B " that is broken up across calls.\r" #define NBODY01C "\n" #define NBODY01D "Now we can try something interesting, like a\nmulti-line buffer. This should not be mangled.\r\n" #define NBODY01E "And a line with a trailing space: \n" #define NBODY02 "Next we'll try a blank.\r" #define NBODY03 "\r\n" #define NBODY04 "Next we'll try multiple blanks.\r\n" #define NBODY05 "Finally we'll try multiple trailing blanks.\r" #define THEADER00 "Received: from client1.football.example.com [192.0.2.1]\r\n" \ " by submitserver.example.com with SUBMISSION;\r\n" \ " Fri, 11 Jul 2003 21:01:54 -0700 (PDT)" #define THEADER01 "From: Joe SixPack " #define THEADER02 "To: Suzie Q " #define THEADER03 "Subject: Is dinner ready?" #define THEADER04 "Date: Fri, 11 Jul 2003 21:00:37 -0700 (PDT)" #define THEADER05 "Message-ID: <20030712040037.46341.5F8J@football.example.com>" #define TBODY "Hi.\r\n" \ "\r\n" \ "We lost the game. Are you hungry yet?\r\n" \ "\r\n" \ "Joe.\r\n" #define KEY "-----BEGIN RSA PRIVATE KEY-----\n" \ "MIICXQIBAAKBgQC4GUGr+d/6SFNzVLYpphnRd0QPGKz2uWnV65RAxa1Pw352Bqiz\n" \ "qiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFgF0gu3UJbNnu3+cd8k/kiQj+q\n" \ "4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3Dyc079gSLtnSrgXb+gQIDAQAB\n" \ "AoGAemlI0opm1Kvs2T4VliH8/tvX5FXbBH8LEZQAUwVeFTB/UQlieXyCV39pIxZO\n" \ "0Sa50qm8YNL9rb5HTSZiHQFOwyAKNqS4m/7JCsbuH4gQkPgPF561BHNL9oKfYgJq\n" \ "9P4kEFfDTBoXKBMxwWtT7AKV8dYvCa3vYzPQ/1BnqQdw2zECQQDyscdgR9Ih59PQ\n" \ "b72ddibdsxS65uXS2vzYLe7SKl+4R5JgJzw0M6DTAnoYFf6JAsKGZM15PCC0E16t\n" \ "RRo47U9VAkEAwjEVrlQ0/8yPACbDggDJg/Zz/uRu1wK0zjqj4vKjleubaX4SEvj7\n" \ "r6xxZm9hC1pMJAC9y3bbkbgCRBjXfyY6fQJBANe5aq2MaZ41wTOPf45NjbKXEiAo\n" \ "SbUpboKCIbyyaa8V/2h0t7D3C0dE9l4efsguqdZoF7Rh2/f1F70QpYRgfJkCQQCH\n" \ "oRrAeGXP50JVW72fNgeJGH/pnghgOa6of0JpxwhENJuGMZxUDfxTtUA6yD3iXP3j\n" \ "A3WL/wbaHsfOYf9Y+g1NAkAGLhx67Ah+uBNK4Xvfz0YPGINX20m+CMsxAw7FOaNv\n" \ "IW2oWFfZCB4APkIis79Ql45AHpavwx5XodBMzZwJUvlL\n" \ "-----END RSA PRIVATE KEY-----\n" #define SMALLKEY "-----BEGIN RSA PRIVATE KEY-----\n" \ "MIIBOwIBAAJBAKmXwtw3FU/88TPoOpYR3FKkD4ViDLQZOSitce6cJzdoksJ2Vs9T\n" \ "l6d1V9OIOsvktC1nmaZ8Xs5I7oMkJF8PbXUCAwEAAQJBAJxAG6NDCNrKY/x8AMZV\n" \ "LFXjm/07KhMgjh4hNzAtJKCRs3NscczUlR/iA//ZmkccSJONmV6WWLo54H5lJPWi\n" \ "jmECIQDS3m6eOt4WY4W4WWC2eMuYeOOIzSK71aWuX4qJVgYZLQIhAM3jzTlssVyh\n" \ "y34LCV4Wap5e2eH/wlpLnHWsVD3sR8JpAiBbxJNtZv8JzUv/e14caxtngoy7F1Mb\n" \ "XZIZ/dhDhl1nDQIhAK3rADDB4BCfm4WdTQxtYyLkfKiro0EjHcdJCuBD91oBAiB3\n" \ "dJk2Cl+yMP+oIqR6bDZQY5lzuaE5v3GMRSSWC94B6A==\n" \ "-----END RSA PRIVATE KEY-----\n" #define PUBLICKEY "v=DKIM1; k=rsa; t=y:s; h=sha1:sha256; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEYNOS "v=DKIM1; k=rsa; t=y; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEY2 "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQ" \ "KBgQDwIRP/UC3SBsEmGqZ9ZJW3/DkMoGeLnQg1fWn7/zYt" \ "IxN2SnFCjxOCKG9v3b4jYfcTNh5ijSsq631uBItLa7od+v" \ "/RtdC2UzJ1lWT947qR+Rcac2gbto/NMqJ0fzfVjH4OuKhi" \ "tdY9tf6mcwGjaNBcWToIMmPSPDdQPNUYckcQ2QIDAQAB" #define PUBLICKEYBADV "v=DKIM0; k=rsa; t=y:s; h=sha1:sha256; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEY256 "v=DKIM1; k=rsa; t=y:s; h=sha256; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEYBADH "v=DKIM1; k=rsa; t=y:s; h=sha0; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEYNOK "v=DKIM1; t=y:s; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEYBADK "v=DKIM1; k=xxx; t=y:s; h=sha1:sha256; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQAB" #define PUBLICKEYEMPTYP "v=DKIM1; k=rsa; t=y:s; h=sha1:sha256; p=" #define PUBLICKEYNOP "v=DKIM1; k=rsa; t=y:s; h=sha1:sha256" #define PUBLICKEYCORRUPTP "v=DKIM1; k=rsa; t=y:s; h=sha1:sha256; p=" \ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4GUGr+d/6SFNzVLYpphnRd0QP" \ "GKz2uWnV65RAxa1Pw352BqizqiKOBjgYGzj8pJQSs8tOvv/2k6jpI809RnESqOFg" \ "F0gu3UJbNnu3+cd8k/kiQj+q4cKKRpAT92ccxc7svhCNgN1sBGmROYZuysG3Vu3D" \ "yc079gSLtnSrgXb+gQIDAQ" #define REPORTRECORD "ra=postmaster; rs=" SMTPTOKENENC #define GIBBERISH "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 !@#$%^&*()_+|-={}[];':,./<>?`~\r\n" OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/tests/t-verifyperf.c000066400000000000000000000200221337314105200246760ustar00rootroot00000000000000/* ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2013, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include "../dkim.h" #include "../dkim-tables.h" #include "t-testdata.h" #define DEFMSGSIZE 1024 #define DEFTESTINT 5 #define BODYBUFRSZ 8192 #define MAXHEADER 4096 #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ char *progname; /* ** CANON_CODE -- convert a canonicalization name to its code ** ** Parameters: ** name -- name to convert ** ** Return value: ** dkim_canon_t */ dkim_canon_t canon_code(char *name) { if (name == NULL) return (dkim_canon_t) DKIM_CANON_UNKNOWN; else if (strcasecmp(name, "simple") == 0) return (dkim_canon_t) DKIM_CANON_SIMPLE; else if (strcasecmp(name, "relaxed") == 0) return (dkim_canon_t) DKIM_CANON_RELAXED; else return (dkim_canon_t) DKIM_CANON_UNKNOWN; } /* ** CANON_NAME -- convert a canonicalization code to its name ** ** Parameters: ** code -- code to convert ** ** Return value: ** Pointer to name string. */ char * canon_name(dkim_canon_t code) { switch (code) { case DKIM_CANON_SIMPLE: return "simple"; case DKIM_CANON_RELAXED: return "relaxed"; case DKIM_CANON_UNKNOWN: default: return "unknown"; } } /* ** ALG_CODE -- convert an algorithm name to its code ** ** Parameters: ** name -- name to convert ** ** Return value: ** dkim_alg_t */ dkim_alg_t alg_code(char *name) { if (name == NULL) return (dkim_alg_t) DKIM_SIGN_UNKNOWN; else if (strcasecmp(name, "rsa-sha1") == 0) return (dkim_alg_t) DKIM_SIGN_RSASHA1; else if (strcasecmp(name, "rsa-sha256") == 0) return (dkim_alg_t) DKIM_SIGN_RSASHA256; else return (dkim_alg_t) DKIM_SIGN_UNKNOWN; } /* ** ALG_NAME -- convert an algorithm code to its name ** ** Parameters: ** code -- code to convert ** ** Return value: ** Pointer to name string. */ char * alg_name(dkim_alg_t code) { switch (code) { case DKIM_SIGN_DEFAULT: return "default"; case DKIM_SIGN_RSASHA1: return "rsa-sha1"; case DKIM_SIGN_RSASHA256: return "rsa-sha256"; case DKIM_SIGN_UNKNOWN: default: return "unknown"; } } /* ** USAGE -- print usage message ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\n" "\t-b bodycanon\tbody canonicalization to use\n" "\t-h hdrcanon \theader canonicalization to use\n" "\t-m bytes \tmessage size in bytes\n" "\t-s signalg \tsigning algorithm to use\n" "\t-t seconds \ttest time in seconds\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** The usual. ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { DKIM_STAT status; u_int verifycnt = 0; int c; int w; int rate; size_t msgsize = DEFMSGSIZE; size_t msgrem; size_t wsz; time_t start = DEFTESTINT; time_t testint = DEFTESTINT; dkim_canon_t hcanon = DKIM_CANON_RELAXED; dkim_canon_t bcanon = DKIM_CANON_SIMPLE; dkim_alg_t signalg = DKIM_SIGN_UNKNOWN; dkim_query_t qtype = DKIM_QUERY_FILE; char *p; DKIM *dkim; DKIM_LIB *lib; dkim_sigkey_t key; unsigned char hdr[MAXHEADER + 1]; unsigned char body[BODYBUFRSZ]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, "b:h:m:s:t:")) != -1) { switch (c) { case 'b': bcanon = canon_code(optarg); if (bcanon == (dkim_canon_t) -1) { fprintf(stderr, "%s: unknown canonicalization '%s'\n", progname, optarg); return EX_USAGE; } break; case 'h': hcanon = canon_code(optarg); if (hcanon == (dkim_canon_t) -1) { fprintf(stderr, "%s: unknown canonicalization '%s'\n", progname, optarg); return EX_USAGE; } break; case 'm': msgsize = strtoul(optarg, &p, 10); if (*p != '\0') { fprintf(stderr, "%s: invalid size '%s'\n", progname, optarg); return EX_USAGE; } break; case 's': signalg = alg_code(optarg); if (signalg == (dkim_alg_t) -1) { fprintf(stderr, "%s: unknown signing algorithm '%s'\n", progname, optarg); return EX_USAGE; } break; case 't': testint = strtoul(optarg, &p, 10); if (*p != '\0') { fprintf(stderr, "%s: invalid seconds '%s'\n", progname, optarg); return EX_USAGE; } break; default: return usage(); } } #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ /* instantiate the library */ lib = dkim_init(NULL, NULL); if (signalg == DKIM_SIGN_UNKNOWN) { if (dkim_libfeature(lib, DKIM_FEATURE_SHA256)) signalg = DKIM_SIGN_RSASHA256; else signalg = DKIM_SIGN_RSASHA1; } else if (signalg == DKIM_SIGN_RSASHA256 && !dkim_libfeature(lib, DKIM_FEATURE_SHA256)) { fprintf(stdout, "### requested signing algorithm not available\n"); dkim_close(lib); return 1; } fprintf(stdout, "*** VERIFYING SPEED TEST: %s/%s with %s, size %u for %lds\n", canon_name(hcanon), canon_name(bcanon), alg_name(signalg), (unsigned int) msgsize, (long) testint); key = KEY; (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, KEYFILE, strlen(KEYFILE)); srandom(time(NULL)); /* prepare a random body buffer */ for (c = 0, w = 0; c < sizeof body; c++) { if (w >= 75 && c < sizeof body - 2) { body[c++] = '\r'; body[c++] = '\n'; w = 0; } body[c++] = (random() + 32) % 127; w++; } /* generate the signature */ dkim = dkim_sign(lib, JOBID, NULL, key, SELECTOR, DOMAIN, hcanon, bcanon, signalg, -1L, &status); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); status = dkim_eoh(dkim); msgrem = msgsize; while (msgrem > 0) { wsz = MIN(msgrem, sizeof body); status = dkim_body(dkim, body, wsz); msgrem -= wsz; } status = dkim_eom(dkim, NULL); memset(hdr, '\0', sizeof hdr); snprintf(hdr, sizeof hdr, "%s: ", DKIM_SIGNHEADER); status = dkim_getsighdr(dkim, hdr + strlen(hdr), sizeof hdr - strlen(hdr), strlen(hdr) + 1); status = dkim_free(dkim); (void) time(&start); /* begin the verify loop */ while (time(NULL) < start + testint) { dkim = dkim_verify(lib, JOBID, NULL, &status); status = dkim_header(dkim, hdr, strlen(hdr)); status = dkim_header(dkim, HEADER02, strlen(HEADER02)); status = dkim_header(dkim, HEADER03, strlen(HEADER03)); status = dkim_header(dkim, HEADER04, strlen(HEADER04)); status = dkim_header(dkim, HEADER05, strlen(HEADER05)); status = dkim_header(dkim, HEADER06, strlen(HEADER06)); status = dkim_header(dkim, HEADER07, strlen(HEADER07)); status = dkim_header(dkim, HEADER08, strlen(HEADER08)); status = dkim_header(dkim, HEADER09, strlen(HEADER09)); status = dkim_eoh(dkim); msgrem = DEFMSGSIZE; while (msgrem > 0) { wsz = MIN(msgrem, sizeof body); status = dkim_body(dkim, body, wsz); msgrem -= wsz; } status = dkim_eom(dkim, NULL); status = dkim_free(dkim); verifycnt++; } dkim_close(lib); rate = verifycnt / testint; fprintf(stdout, "*** %u messages verified (%d msgs/sec)\n", verifycnt, rate); return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/util.c000066400000000000000000000356641337314105200221110ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #include #include /* libopendkim includes */ #include "dkim-internal.h" #include "util.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ /* ** DKIM_COLLAPSE -- remove spaces from a string ** ** Parameters: ** str -- string to process ** ** Return value: ** None. */ void dkim_collapse(u_char *str) { u_char *q; u_char *r; assert(str != NULL); for (q = str, r = str; *q != '\0'; q++) { if (!isspace(*q)) { if (q != r) *r = *q; r++; } } *r = '\0'; } /* ** DKIM_HDRLIST -- build up a header list for use in a regexp ** ** Parameters: ** buf -- where to write ** buflen -- bytes at "buf" ** hdrlist -- array of header names ** first -- first call ** ** Return value: ** TRUE iff everything fit. */ _Bool dkim_hdrlist(u_char *buf, size_t buflen, u_char **hdrlist, _Bool first) { _Bool escape = FALSE; int c; int len; u_char *p; u_char *q; u_char *end; assert(buf != NULL); assert(hdrlist != NULL); for (c = 0; ; c++) { if (hdrlist[c] == NULL) break; if (!first) { len = strlcat((char *) buf, "|", buflen); if (len >= buflen) return FALSE; } else { len = strlen((char *) buf); } first = FALSE; q = &buf[len]; end = &buf[buflen - 1]; for (p = hdrlist[c]; *p != '\0'; p++) { if (q >= end) return FALSE; if (escape) { *q = *p; q++; escape = FALSE; } switch (*p) { case '*': *q = '.'; q++; if (q >= end) return FALSE; *q = '*'; q++; break; case '.': *q = '\\'; q++; if (q >= end) return FALSE; *q = '.'; q++; break; case '\\': escape = TRUE; break; default: *q = *p; q++; break; } } } return TRUE; } /* ** DKIM_LOWERHDR -- convert a string (presumably a header) to all lowercase, ** but only up to a colon ** ** Parameters: ** str -- string to modify ** ** Return value: ** None. */ void dkim_lowerhdr(unsigned char *str) { unsigned char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (*p == ':') return; if (isascii(*p) && isupper(*p)) *p = tolower(*p); } } /* ** DKIM_HEXCHAR -- translate a hexadecimal character ** ** Parameters: ** c -- character to translate ** ** Return value: ** Decimal equivalent. */ int dkim_hexchar(int c) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return c - '0'; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return 10 + c - 'A'; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return 10 + c - 'a'; default: assert(0); return -1; } } /* ** DKIM_QP_ENCODE -- encode a string as quoted-printable ** ** Parameters: ** in -- input ** out -- output ** outlen -- bytes available at "out" ** ** Return value: ** >= 0 -- number of bytes in output ** -1 -- failure (not enough space) ** ** Notes: ** The function does not guarantee string termination. */ int dkim_qp_encode(unsigned char *in, unsigned char *out, int outlen) { unsigned char const *p; unsigned char *q; unsigned char *end; size_t len; assert(in != NULL); assert(out != NULL); end = out + outlen; len = 0; for (p = in, q = out; *p != '\0'; p++) { if (q >= end) return -1; if ((*p >= 0x21 && *p <= 0x3a) || *p == 0x3c || (*p >= 0x3e && *p <= 0x7e)) { *q = *p; q++; len++; } else if (q < end - 4) { snprintf((char *) q, 4, "=%02X", *p); q += 3; len += 3; } } return len; } /* ** DKIM_QP_DECODE -- decode a quoted-printable string ** ** Parameters: ** in -- input ** out -- output ** outlen -- bytes available at "out" ** ** Return value: ** >= 0 -- number of bytes in output ** -1 -- parse error ** ** Notes: ** The returned number of bytes can be larger than "outlen" if ** "out" wasn't big enough to contain the decoded output. The function ** does not guarantee string termination. */ int dkim_qp_decode(unsigned char *in, unsigned char *out, int outlen) { unsigned char next1; unsigned char next2 = 0; int xl; int decode = 0; unsigned char const *p; unsigned char *q; unsigned char *pos; unsigned char const *start; unsigned char const *stop; unsigned char *end; char const *hexdigits = "0123456789ABCDEF"; assert(in != NULL); assert(out != NULL); start = NULL; stop = NULL; end = out + outlen; for (p = in, q = out; *p != '\0'; p++) { switch (*p) { case '=': next1 = *(p + 1); if (next1 != '\0') next2 = *(p + 2); /* = at EOL */ if (next1 == '\n' || (next1 == '\r' && next2 == '\n')) { stop = p; if (start != NULL) { unsigned char const *x; for (x = start; x <= stop; x++) { decode++; if (q <= end) { *q = *x; q++; } } } start = NULL; stop = NULL; p++; if (next2 == '\n') p++; break; } /* = elsewhere */ pos = (unsigned char *) strchr(hexdigits, next1); if (pos == NULL) return -1; xl = (pos - (unsigned char *) hexdigits) * 16; pos = (unsigned char *) strchr(hexdigits, next2); if (pos == NULL) return -1; xl += (pos - (unsigned char *) hexdigits); stop = p; if (start != NULL) { unsigned char const *x; for (x = start; x < stop; x++) { decode++; if (q <= end) { *q = *x; q++; } } } start = NULL; stop = NULL; if (q <= end) { *q = xl; q++; } decode++; p += 2; break; case ' ': case '\t': if (start == NULL) start = p; break; case '\r': break; case '\n': if (stop == NULL) stop = p; if (start != NULL) { unsigned char const *x; for (x = start; x <= stop; x++) { decode++; if (q <= end) { *q = *x; q++; } } } if (p > in && *(p - 1) != '\r') { decode++; if (q <= end) { *q = '\n'; q++; } } else { decode += 2; if (q <= end) { *q = '\r'; q++; } if (q <= end) { *q = '\n'; q++; } } start = NULL; stop = NULL; break; default: if (start == NULL) start = p; stop = p; break; } } if (start != NULL) { unsigned char const *x; for (x = start; x < p; x++) { decode++; if (q <= end) { *q = *x; q++; } } } return decode; } #ifdef NEED_FAST_STRTOUL /* ** DKIM_STRTOUL -- convert string to unsigned long ** ** Parameters: ** str -- string to convert ** endptr -- pointer to store string after value ** base -- base to convert from ** ** Return value: ** Value of string as unsigned long */ unsigned long dkim_strtoul(const char *str, char **endptr, int base) { char start = '+'; static char cutlim = ULONG_MAX % 10; char c; _Bool erange = FALSE; static unsigned long cutoff = ULONG_MAX / 10; unsigned long value = 0; const char *subj; const char *cur; if (base != 10) return strtoul(str, endptr, base); if (str == NULL) { errno = EINVAL; return value; } subj = str; while (*subj != '\0' && isspace(*subj)) subj++; if (*subj == '-' || *subj == '+') start = *subj++; for (cur = subj; *cur >= '0' && *cur <= '9'; cur++) { if (erange) continue; c = *cur - '0'; if ((value > cutoff) || (value == cutoff && c > cutlim)) { erange = TRUE; continue; } value = (value * 10) + c; } if (cur == subj) { if (endptr != NULL) *endptr = (char *) str; errno = EINVAL; return 0; } if (endptr != NULL) *endptr = (char *) cur; if (erange) { errno = ERANGE; return ULONG_MAX; } if (start == '-') return -value; else return value; } /* ** DKIM_STRTOULL -- convert string to unsigned long long ** ** Parameters: ** str -- string to convert ** endptr -- pointer to store string after value ** base -- base to convert from ** ** Return value: ** Value of string as unsigned long long */ unsigned long long dkim_strtoull(const char *str, char **endptr, int base) { char start = '+'; char c; _Bool erange = FALSE; static char cutlim = ULLONG_MAX % 10; static unsigned long long cutoff = ULLONG_MAX / 10; unsigned long long value = 0; const char *subj; const char *cur; if (base != 10) return strtoull(str, endptr, base); if (str == NULL) { errno = EINVAL; return value; } subj = str; while (*subj && isspace(*subj)) subj++; if (*subj == '-' || *subj == '+') start = *subj++; for (cur = subj; *cur >= '0' && *cur <= '9'; cur++) { if (erange) continue; c = *cur - '0'; if ((value > cutoff) || (value == cutoff && c > cutlim)) { erange = 1; continue; } value = (value * 10) + c; } if (cur == subj) { if (endptr != NULL) *endptr = (char *) str; errno = EINVAL; return 0; } if (endptr != NULL) *endptr = (char *) cur; if (erange != 0) { errno = ERANGE; return ULLONG_MAX; } if (start == '-') return -value; else return value; } #endif /* NEED_FAST_STRTOUL */ /* ** DKIM_CHECK_DNS_REPLY -- see if a DNS reply is truncated or corrupt ** ** Parameters: ** ansbuf -- answer buffer ** anslen -- number of bytes returned ** xclass -- expected class ** xtype -- expected type ** ** Return value: ** 2 -- reply not usable ** 1 -- reply truncated but usable ** 0 -- reply intact (but may not be what you want) ** -1 -- other error */ int dkim_check_dns_reply(unsigned char *ansbuf, size_t anslen, int xclass, int xtype) { _Bool trunc = FALSE; int qdcount; int ancount; int n; uint16_t type = (uint16_t) -1; uint16_t class = (uint16_t) -1; unsigned char *cp; unsigned char *eom; HEADER hdr; unsigned char name[DKIM_MAXHOSTNAMELEN + 1]; assert(ansbuf != NULL); /* set up pointers */ memcpy(&hdr, ansbuf, sizeof hdr); cp = ansbuf + HFIXEDSZ; eom = ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) ansbuf, eom, cp, (RES_UNC_T) name, sizeof name); if ((n = dn_skipname(cp, eom)) < 0) return 2; cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return 2; GETSHORT(type, cp); GETSHORT(class, cp); } if (type != xtype || class != xclass) return 0; /* if NXDOMAIN, return DKIM_STAT_NOKEY */ if (hdr.rcode == NXDOMAIN) return 0; /* if truncated, we can't do it */ if (hdr.tc) trunc = TRUE; /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) return (trunc ? 2 : 0); /* ** Extract the data from the first TXT answer. */ while (--ancount >= 0 && cp < eom) { /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) ansbuf, eom, cp, (RES_UNC_T) name, sizeof name)) < 0) return 2; /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ + INT32SZ > eom) return 2; GETSHORT(type, cp); cp += INT16SZ; /* class */ cp += INT32SZ; /* ttl */ /* skip CNAME if found; assume it was resolved */ if (type == T_CNAME) { if ((n = dn_expand((u_char *) ansbuf, eom, cp, (RES_UNC_T) name, sizeof name)) < 0) return 2; cp += n; continue; } else if (type != xtype) { return (trunc ? 1 : 0); } /* found a record we can use; break */ break; } /* if ancount went below 0, there were no good records */ if (ancount < 0) return (trunc ? 1 : 0); /* get payload length */ if (cp + INT16SZ > eom) return 2; GETSHORT(n, cp); /* ** XXX -- maybe deal with a partial reply rather than require ** it all */ if (cp + n > eom) return 2; return (trunc ? 1 : 0); } /* ** DKIM_MIN_TIMEVAL -- determine the timeout to apply before reaching ** one of two timevals ** ** Parameters: ** t1 -- first timeout (absolute) ** t2 -- second timeout (absolute) (may be NULL) ** t -- final timeout (relative) ** which -- which of t1 and t2 hit first ** ** Return value: ** None. */ void dkim_min_timeval(struct timeval *t1, struct timeval *t2, struct timeval *t, struct timeval **which) { struct timeval *next; struct timeval now; assert(t1 != NULL); assert(t != NULL); if (t2 == NULL || t2->tv_sec > t1->tv_sec || (t2->tv_sec == t1->tv_sec && t2->tv_usec > t1->tv_usec)) next = t1; else next = t2; (void) gettimeofday(&now, NULL); if (next->tv_sec < now.tv_sec || (next->tv_sec == now.tv_sec && next->tv_usec < now.tv_usec)) { t->tv_sec = 0; t->tv_usec = 0; } else { t->tv_sec = next->tv_sec - now.tv_sec; if (next->tv_usec < now.tv_usec) { t->tv_sec--; t->tv_usec = next->tv_usec - now.tv_usec + 1000000; } else { t->tv_usec = next->tv_usec - now.tv_usec; } } if (which != NULL) *which = next; } /* ** DKIM_COPY_ARRAY -- copy an array of char pointers ** ** Parameters: ** in -- input array, must be NULL-terminated ** ** Return value: ** A copy of "in" and its elements, or NULL on failure. */ const char ** dkim_copy_array(char **in) { unsigned int c; unsigned int n; char **out; assert(in != NULL); for (n = 0; in[n] != NULL; n++) continue; out = malloc(sizeof(char *) * (n + 1)); for (c = 0; c < n; c++) { out[c] = strdup(in[c]); if (out[c] == NULL) { for (n = 0; n < c; n++) free(out[n]); free(out); return NULL; } } out[c] = NULL; return (const char **) out; } /* ** DKIM_CLOBBER_ARRAY -- clobber a cloned array of char pointers ** ** Parameters: ** in -- input array, must be NULL-terminated ** ** Return value: ** None. */ void dkim_clobber_array(char **in) { unsigned int n; assert(in != NULL); for (n = 0; in[n] != NULL; n++) free(in[n]); free(in); } /* ** DKIM_STRISPRINT -- return TRUE iff a string contains only isprint() characters ** ** Parameters: ** str -- string to evaluate ** ** Return value: ** TRUE unless a non-isprint was found */ _Bool dkim_strisprint(unsigned char *str) { unsigned char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (!isprint(*p)) return FALSE; } return TRUE; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libopendkim/util.h000066400000000000000000000031071337314105200221010ustar00rootroot00000000000000/* ** Copyright (c) 2005, 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, 2015, The Trusted Domain Project. ** All rights reserved. */ #ifndef _UTIL_H_ #define _UTIL_H_ #include "build-config.h" /* system includes */ #include #include #ifdef USE_UNBOUND # include #endif /* USE_UNBOUND */ #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ /* prototypes */ extern int dkim_addrcmp __P((u_char *, u_char *)); extern int dkim_check_dns_reply __P((unsigned char *ansbuf, size_t anslen, int xclass, int xtype)); extern void dkim_clobber_array __P((char **)); extern void dkim_collapse __P((u_char *)); extern const char **dkim_copy_array __P((char **)); extern _Bool dkim_hdrlist __P((u_char *, size_t, u_char **, _Bool)); extern int dkim_hexchar __P((int c)); extern void dkim_lowerhdr __P((u_char *)); extern void dkim_min_timeval __P((struct timeval *, struct timeval *, struct timeval *, struct timeval **)); extern int dkim_qp_decode __P((u_char *, u_char *, int)); extern int dkim_qp_encode __P((u_char *, u_char *, int)); extern _Bool dkim_strisprint __P((u_char *)); #ifdef NEED_FAST_STRTOUL extern unsigned long dkim_strtoul __P((const char *str, char **endptr, int base)); extern unsigned long long dkim_strtoull __P((const char *str, char **endptr, int base)); #endif /* NEED_FAST_STRTOUL */ #endif /* ! _UTIL_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/librbl/000077500000000000000000000000001337314105200177235ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/librbl/Makefile.am000066400000000000000000000006101337314105200217540ustar00rootroot00000000000000# Copyright (c) 2010, 2012, The Trusted Domain Project. All rights reserved. # lib_LTLIBRARIES = librbl.la librbl_la_SOURCES = rbl.c librbl_la_LDFLAGS = -version-info 1:0:0 $(LIBRESOLV) librblincludedir = $(includedir)/rbl librblinclude_HEADERS = rbl.h if RPATH librbl_la_LDFLAGS += -rpath $(libdir) endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = rbl.pc dist_man_MANS = rbl.3 OpenDKIM-rel-opendkim-2-11-0-Beta2/librbl/rbl.3000066400000000000000000000263041337314105200205730ustar00rootroot00000000000000.TH librbl 3 .SH NAME .B rbl_init(), rbl_close(), rbl_geterror(), rbl_setdomain(), .B rbl_query_start(), rbl_query_check(), rbl_query_cancel(), .B rbl_settimeout(), rbl_setcallbackint(), rbl_setcallbackctx(), .B rbl_setdnscallback(), rbl_dns_set_query_service(), .B rbl_dns_set_query_start(), rbl_dns_set_query_cancel(), .B rbl_dns_set_query_waitreply(), rbl_dns_set_init(), rbl_dns_set_close(), .B rbl_dns_set_nslist(), rbl_dns_set_config(), rbl_dns_set_trustanchor(), .B rbl_dns_init() \- Realtime Blacklist (RBL) service facility .SH SYNOPSIS #include .I RBL * .B rbl_init (void *(* .B mallocf )(void *, size_t), void (* .B freef )(void *, void *p), void * .B closure ); unsigned char * .B rbl_geterror (RBL * .B rbl ); void .B rbl_setdomain (RBL * .B rbl, unsigned char * .B qroot ); RBL_STAT .B rbl_query_start (RBL * .B rbl, unsigned char * .B query, void ** .B qh ); RBL_STAT .B rbl_settimeout (RBL * .B rbl, unsigned int .B timeout ); RBL_STAT .B rbl_setcallbackint (RBL * .B rbl, unsigned int .B cbint ); RBL_STAT .B rbl_setcallbackctx (RBL *, .B rbl, void * .B ctx ); RBL_STAT .B rbl_setdnscallback (RBL *, .B rbl, void (* .B func )(const void *)); void * .B rbl_dns_set_query_service (RBL * .B rbl, void * .B svc ); void .B rbl_dns_set_query_cancel (RBL * .B rbl, int (* .B func )(void *, void *)); void .B rbl_dns_set_query_start (RBL * .B rbl, int (* .B func )(void *, int, unsigned char *, unsigned char *, size_t, void **)); void .B rbl_dns_set_query_waitreply (RBL * .B rbl, int (* .B func )(void *, void *, struct timeval *, size_t *, int *, int *)); void .B rbl_dns_set_init (RBL * .B rbl, int (* .B func )(void **); void .B rbl_dns_set_close (RBL * .B rbl, int (* .B func )(void *); void .B rbl_dns_set_config (RBL * .B rbl, int (* .B func )(void *, const char *); void .B rbl_dns_set_nslist (RBL * .B rbl, int (* .B func )(void *, const char *); void .B rbl_dns_set_trustanchor (RBL * .B rbl, int (* .B func )(void *, const char *); RBL_STAT .B rbl_dns_init (RBL * .B rbl ); void .B rbl_close (RBL * .B rbl ); .SH DESCRIPTION These functions are an interface to a facility to conduct Realtime Blacklist (RBL) queries and return their results. RBLs are described in RFC5782. An application first initializes the package by calling .B rbl_init(). The optional .I mallocf parameter is a caller-provided memory allocation function taking a pointer to a caller-provided opaque data structure (the .I closure parameter) and a number of bytes to allocate. If .I mallocf is not provided, the default system memory allocator function .B malloc(3) is used. The optional .I freef parameter specifies a matching caller-provided memory deallocator function, taking a pointer to a caller-provided opaque data structure (the .I closure parameter) and a pointer to the memory to be released. If .I freef is not provided, the default system memory release function .B free(3) is used. A handle for future use of the initialized library instance is returned, or NULL on error and .I errno will be set to indicate the cause of the failure. The .B rbl_geterror() function can be used to poll the library for an error string that provides further description for the most recent failed operation. A call to .B rbl_setdomain() sets the RBL's base domain. This specifies the "root" of all future queries for the provided .B rbl handle to .B qroot. Future queries passed to this handle will be prepended to the string provided here. A query is initialized with a call to .B rbl_query_start() which takes an RBL library handle as .B rbl, the string to be queried as .B query, and a pointer to a void pointer that will be updated to contain a reference to the initiated query as .B qh. A query previously started by .I rbl_query_start() can be canceled by calling .B rbl_query_cancel(), passing it an RBL library handle as .B rbl and a query handle as .B qh as previously returned when the query was started. A query previously started by .I rbl_query_start() can be polled for its status or a result using .B rbl_query_check(), passing it an RBL library handle as .B rbl, a query handle as .B qh, a pointer to a "struct timeval" ast .B timeout (which can be NULL if an infinite wait is acceptable), and a pointer to a 32-bit integer as .B res into which any result will be returned (or it can be NULL if the caller doesn't actually want the result). Results are in network byte order. If this function returns RBL_STAT_FOUND or RBL_STAT_NOTFOUND, the query is automatically canceled and need not be passed to .I rbl_query_cancel(). The .B rbl_settimeout() function can be used to change the query timeout. The default is ten seconds. If it is useful to have the library periodically call a user-provided function as an indication that queries are still in progress, such a function can be registered with the .B rbl_setdnscallback() function. The function provided should take a void context pointer as its sole argument. .B rbl_setcallbackctx() is used to tell the library what context pointer should be used, and .B rbl_setcallbackint() is used to tell the library what frequency, in seconds, should be used to call that callback function. Each of these takes the corresponding RBL library handle as its first argument, and the obvious parameter for its second. By default, the library will use the stock system resolver to conduct DNS queries. If alternates should be used, these can be specified using the following functions: .B rbl_dns_set_query_service() sets a context pointer to the query service to be used, if any. This will be passed as-is to the other DNS functions. It returns its previous value. .B rbl_dns_set_query_cancel() sets a pointer to the function that should be called to cancel an open query, and should take the following parameters: a void pointer to the DNS query service to be used, and a void pointer to a query handle as previously returned by a call to .I rbl_dns_set_query_start(). The function should return one of the DNS result codes described below. .B rbl_dns_set_query_start() sets a pointer to the function that should be called to initiate a new query, and should take the following parameters: a void pointer to the DNS query service to be used, a DNS record type (e.g. T_TXT), a pointer to a string containing the query to be started, a pointer to a buffer into which the reply should be written, the number of bytes available in that buffer, and a pointer to a void pointer that will be updated to contain a unique handle for that query once started. The function should return one of the DNS result codes described below. .B rbl_dns_set_query_waitreply() sets a pointer to the function that should be called to wait for a reply to an open query, and should take the following parameters: a void pointer to the DNS query service to be used, a void pointer referencing the query of interest as previously returned by a call to .I rbl_dns_set_query_start(), a pointer to a "struct timeval" structure indicating how long the function should wait for a reply (or NULL if infinite waiting is acceptable), a pointer to a "size_t" that will be updated to contain the size of the received reply, a pointer to an integer that will contain an error code if the query fails (can be NULL if that information is not interesting to the caller), and a pointer to an integer that will contain a DNSSEC status indication (can be NULL if that information is not interesting to the caller). The function should return one of the DNS result codes described below. .B rbl_dns_set_init() sets a pointer to the function that should be called when it is necessary to initialize a resolver. The function should store a handle to the initialized resolver and return zero, or return non-zero if initialization could not be completed. The function specified here is called before the first call to the query start function (see above). .B rbl_dns_set_close() sets a pointer to the function that should be called when it is necessary to terminate a resolver. The function will receive a handle referencing the resolver to be terminated, and should return zero on success or non-zero on failure. .B rbl_dns_set_nslist() sets a pointer to the function that should be called when it is necessary to change the set of nameservers that are to be used to resolve RBL queries. The function will receive a handle referencing the active resolver and a string containing a comma-separated list of nameservers to use. It should return zero on success and non-zero on failure. .B rbl_dns_set_config() sets a pointer to the function that should be called when it is necessary to provide arbitrary configuration information to the resolver. The function will receive a handle referencing the active resolver and a string containing the configuration. It should return zero on success and non-zero on failure. .B rbl_dns_set_trustanchor() sets a pointer to the function that should be called when it is necessary to provide trust anchor information (supporting DNSSEC) to the resolver. The function will receive a handle referencing the active resolver and a string containing the trust anchor data. It should return zero on success and non-zero on failure. Calling .B rbl_dns_init() forces (re-)initialization of the resolver. This essentially causes the library to call any initialization function defined by .B rbl_dns_set_init(). When the library handle is no longer needed, it should be passed to .B rbl_close(). .SH RETURN VALUES The following return codes, of type RBL_STAT, can be returned: .TP .I RBL_STAT_OK successful completion .TP .I RBL_STAT_INVALID operation failed because an invalid parameter was provided .TP .I RBL_STAT_DNSERROR operation could not be completed because of errors requesting or receiving a DNS reply; note that this does not include a successful reply that contains a "no record found" result, which is a successful answer .TP .I RBL_STAT_NORESOURCE a caller-provided buffer was too small to complete the requested operation, or a memory or file descriptor allocation failed .TP .I RBL_STAT_NOTIMPLEMENT an optional library feature was not selected at compilation time .TP .I RBL_STAT_FOUND the requested record was found in the RBL .TP .I RBL_STAT_NOTFOUND the requested record was not found in the RBL (but the query did complete) .TP .I RBL_STAT_NOREPLY a call to .I rbl_query_check() timed out before a result could be returned .TP .I RBL_STAT_EXPIRED the underlying resolver reported that the query expired; this is included to support resolvers that have an overall query timeout as well as a single wait timeout .SH DNS RETURN CODES Any registered DNS functions should return one of the following result codes: .TP .I RBL_DNS_ERROR An error occurred. The cause of the error can be retrieved using .I rbl_geterror(). .TP .I RBL_DNS_SUCCESS The operation was successful. .TP .I RBL_DNS_REPLY A reply is available (returned by the "waitreply" function). .TP .I RBL_DNS_NOREPLY No reply was received by the time the query timeout was reached (returned by the "waitreply" function). .TP .I RBL_DNS_EXPIRED The query expired completely (returned by the "waitreply" function). Some resolvers set an overall timeout for the query at start time in addition to one for each single wait request; this code indicates the former timeout expired. .SH COPYRIGHT Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I intro(2) OpenDKIM-rel-opendkim-2-11-0-Beta2/librbl/rbl.c000066400000000000000000000621131337314105200206510ustar00rootroot00000000000000/* ** Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #include /* librbl includes */ #include "rbl.h" /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ #ifndef T_RRSIG # define T_RRSIG 46 #endif /* ! T_RRSIG */ /* struct rbl_query -- an open RBL query */ struct rbl_query { void * rq_qh; size_t rq_anslen; u_char rq_buf[HFIXEDSZ + MAXPACKET]; }; /* struct rbl_handle -- an RBL library context */ struct rbl_handle { u_int rbl_timeout; u_int rbl_cbint; void * rbl_cbctx; void * rbl_closure; void * (*rbl_malloc) (void *closure, size_t nbytes); void (*rbl_free) (void *closure, void *p); void (*rbl_dns_callback) (const void *context); void * rbl_dns_service; int (*rbl_dns_init) (void **srv); void (*rbl_dns_close) (void *srv); int (*rbl_dns_start) (void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh); int (*rbl_dns_cancel) (void *srv, void *qh); int (*rbl_dns_config) (void *srv, const char *config); int (*rbl_dns_trustanchor) (void *srv, const char *trust); int (*rbl_dns_setns) (void *srv, const char *ns); int (*rbl_dns_waitreply) (void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec); u_char rbl_qroot[RBL_MAXHOSTNAMELEN + 1]; u_char rbl_error[RBL_MAXERRORSTRING + 1]; }; /* ** Standard UNIX resolver stub functions */ struct rbl_res_qh { int rq_error; size_t rq_buflen; }; /* ** RBL_RES_CANCEL -- cancel a pending resolver query ** ** Parameters: ** srv -- query service handle (ignored) ** qh -- query handle (ignored) ** ** Return value: ** 0 on success, !0 on error ** ** Notes: ** The standard UNIX resolver is synchronous, so in theory this can ** never get called. We have not yet got any use cases for one thread ** canceling another thread's pending queries, so for now just return 0. */ static int rbl_res_cancel(void *srv, void *qh) { if (qh != NULL) free(qh); return 0; } /* ** RBL_RES_QUERY -- initiate a DNS query ** ** Parameters: ** srv -- service handle (ignored) ** type -- RR type to query ** query -- the question to ask ** buf -- where to write the answer ** buflen -- bytes at "buf" ** qh -- query handle, used with rbl_res_waitreply ** ** Return value: ** An RBL_DNS_* constant. ** ** Notes: ** This is a stub for the stock UNIX resolver (res_) functions, which ** are synchronous so no handle needs to be created, so "qh" is set to ** "buf". "buf" is actually populated before this returns (unless ** there's an error). */ static int rbl_res_query(void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh) { int n; int ret; struct rbl_res_qh *rq; unsigned char qbuf[HFIXEDSZ + MAXPACKET]; #ifdef HAVE_RES_NINIT struct __res_state statp; #endif /* HAVE_RES_NINIT */ #ifdef HAVE_RES_NINIT memset(&statp, '\0', sizeof statp); res_ninit(&statp); #endif /* HAVE_RES_NINIT */ #ifdef HAVE_RES_NINIT n = res_nmkquery(&statp, QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf, sizeof qbuf); #else /* HAVE_RES_NINIT */ n = res_mkquery(QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf, sizeof qbuf); #endif /* HAVE_RES_NINIT */ if (n == (size_t) -1) { #ifdef HAVE_RES_NINIT res_nclose(&statp); #endif /* HAVE_RES_NINIT */ return RBL_DNS_ERROR; } #ifdef HAVE_RES_NINIT ret = res_nsend(&statp, qbuf, n, buf, buflen); #else /* HAVE_RES_NINIT */ ret = res_send(qbuf, n, buf, buflen); #endif /* HAVE_RES_NINIT */ if (ret == -1) { #ifdef HAVE_RES_NINIT res_nclose(&statp); #endif /* HAVE_RES_NINIT */ return RBL_DNS_ERROR; } #ifdef HAVE_RES_NINIT res_nclose(&statp); #endif /* HAVE_RES_NINIT */ rq = (struct rbl_res_qh *) malloc(sizeof *rq); if (rq == NULL) return RBL_DNS_ERROR; if (ret == -1) { rq->rq_error = errno; rq->rq_buflen = 0; } else { rq->rq_error = 0; rq->rq_buflen = (size_t) ret; } *qh = (void *) rq; return RBL_DNS_SUCCESS; } /* ** RBL_RES_WAITREPLY -- wait for a reply to a pending query ** ** Parameters: ** srv -- service handle ** qh -- query handle ** to -- timeout ** bytes -- number of bytes in the reply (returned) ** error -- error code (returned) ** ** Return value: ** A RBL_DNS_* code. ** ** Notes: ** Since the stock UNIX resolver is synchronous, the reply was completed ** before rbl_res_query() returned, and thus this is almost a no-op. */ int rbl_res_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec) { struct rbl_res_qh *rq; assert(qh != NULL); rq = qh; if (bytes != NULL) *bytes = rq->rq_buflen; if (error != NULL) *error = rq->rq_error; return RBL_DNS_SUCCESS; } /* ** RBL_RES_SETNS -- set nameserver list ** ** Parameters: ** srv -- service handle ** nslist -- nameserver list, as a string ** ** Return value: ** 0 -- success ** !0 -- error */ int rbl_res_nslist(void *srv, const char *nslist) { #ifdef HAVE_RES_SETSERVERS int nscount = 0; char *tmp; char *ns; char *last = NULL; struct sockaddr_in in; # ifdef AF_INET6 struct sockaddr_in6 in6; # endif /* AF_INET6 */ struct state *res; res_sockaddr_union nses[MAXNS]; assert(srv != NULL); assert(nslist != NULL); memset(nses, '\0', sizeof nses); tmp = strdup(nslist); if (tmp == NULL) return -1; for (ns = strtok_r(tmp, ",", &last); ns != NULL && nscount < MAXNS; ns = strtok_r(NULL, ",", &last) { memset(&in, '\0', sizeof in); # ifdef AF_INET6 memset(&in6, '\0', sizeof in6); # endif /* AF_INET6 */ if (inet_pton(AF_INET, ns, (struct in_addr *) &in.sin_addr, sizeof in.sin_addr) == 1) { in.sin_family= AF_INET; in.sin_port = htons(DNSPORT); memcpy(&nses[nscount].sin, &in, sizeof nses[nscount].sin); nscount++; } # ifdef AF_INET6 else if (inet_pton(AF_INET6, ns, (struct in6_addr *) &in6.sin6_addr, sizeof in6.sin6_addr) == 1) { in6.sin6_family= AF_INET6; in6.sin6_port = htons(DNSPORT); memcpy(&nses[nscount].sin6, &in6, sizeof nses[nscount].sin6); nscount++; } # endif /* AF_INET6 */ else { free(tmp); return -1; } } res = srv; res_setservers(res, nses, nscount); free(tmp); #endif /* HAVE_RES_SETSERVERS */ return 0; } /* ** RBL_RES_CLOSE -- shut down the resolver ** ** Parameters: ** srv -- service handle ** ** Return value: ** None. */ void rbl_res_close(void *srv) { #ifdef HAVE_RES_NINIT struct state *res; res = srv; res_nclose(res); free(res); #endif /* HAVE_RES_NINIT */ } /* ** RBL_INIT -- initialize an RBL handle ** ** Parameters: ** caller_mallocf -- caller-provided memory allocation function ** caller_freef -- caller-provided memory release function ** closure -- memory closure to pass to the above when used ** ** Return value: ** A new RBL handle suitable for use with other RBL functions, or ** NULL on failure. ** ** Side effects: ** Sudden changes in local density altitude. */ RBL * rbl_init(void *(*caller_mallocf)(void *closure, size_t nbytes), void (*caller_freef)(void *closure, void *p), void *closure) { RBL *new; if (caller_mallocf == NULL) new = (RBL *) malloc(sizeof(struct rbl_handle)); else new = caller_mallocf(closure, sizeof(struct rbl_handle)); if (new == NULL) return NULL; memset(new, '\0', sizeof(struct rbl_handle)); new->rbl_timeout = RBL_DEFTIMEOUT; new->rbl_closure = closure; new->rbl_malloc = caller_mallocf; new->rbl_free = caller_freef; new->rbl_dns_start = rbl_res_query; new->rbl_dns_waitreply = rbl_res_waitreply; new->rbl_dns_cancel = rbl_res_cancel; new->rbl_dns_setns = rbl_res_nslist; new->rbl_dns_close = rbl_res_close; return new; } /* ** RBL_CLOSE -- shut down a RBL instance ** ** Parameters: ** rbl -- RBL handle to shut down ** ** Return value: ** None. */ void rbl_close(RBL *rbl) { assert(rbl != NULL); if (rbl->rbl_dns_service != NULL && rbl->rbl_dns_close != NULL) (void) rbl->rbl_dns_close(rbl->rbl_dns_service); if (rbl->rbl_free != NULL) rbl->rbl_free(rbl->rbl_closure, rbl); else free(rbl); } /* ** RBL_GETERROR -- return any stored error string from within the RBL ** context handle ** ** Parameters: ** rbl -- RBL handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ const u_char * rbl_geterror(RBL *rbl) { assert(rbl != NULL); return rbl->rbl_error; } /* ** RBL_SETDOMAIN -- declare the RBL's domain (the query root) ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** qroot -- query root ** ** Return value: ** None (yet). */ void rbl_setdomain(RBL *rbl, u_char *qroot) { assert(rbl != NULL); assert(qroot != NULL); strncpy(rbl->rbl_qroot, qroot, sizeof rbl->rbl_qroot); rbl->rbl_qroot[sizeof rbl->rbl_qroot - 1] = '\0'; } /* ** RBL_SETTIMEOUT -- set the DNS timeout ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** timeout -- requested timeout (seconds) ** ** Return value: ** None. */ void rbl_settimeout(RBL *rbl, u_int timeout) { assert(rbl != NULL); rbl->rbl_timeout = timeout; } /* ** RBL_SETCALLBACKINT -- set the DNS callback interval ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** cbint -- requested callback interval (seconds) ** ** Return value: ** None. */ void rbl_setcallbackint(RBL *rbl, u_int cbint) { assert(rbl != NULL); rbl->rbl_cbint = cbint; } /* ** RBL_SETCALLBACKCTX -- set the DNS callback context ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** ctx -- context to pass to the DNS callback ** ** Return value: ** None. */ void rbl_setcallbackctx(RBL *rbl, void *ctx) { assert(rbl != NULL); rbl->rbl_cbctx = ctx; } /* ** RBL_SETDNSCALLBACK -- set the DNS wait callback ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** func -- function to call; should take an opaque context pointer ** ** Return value: ** None. */ void rbl_setdnscallback(RBL *rbl, void (*func)(const void *context)) { assert(rbl != NULL); rbl->rbl_dns_callback = func; } /* ** RBL_DNS_SET_QUERY_SERVICE -- stores a handle representing the DNS ** query service to be used, returning any ** previous handle ** ** Parameters: ** rbl -- RBL library handle ** h -- handle to be used ** ** Return value: ** Previously stored handle, or NULL if none. */ void * rbl_dns_set_query_service(RBL *rbl, void *h) { void *old; assert(rbl != NULL); old = rbl->rbl_dns_service; rbl->rbl_dns_service = h; return old; } /* ** RBL_DNS_SET_QUERY_START -- stores a pointer to a query start function ** ** Parameters: ** rbl -- RBL library handle ** func -- function to use to start queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- receives handle stored by ** rbl_dns_set_query_service() ** int type -- DNS RR query type (C_IN assumed) ** char *query -- question to ask ** char *buf -- buffer into which to write reply ** size_t buflen -- size of buf ** void **qh -- returned query handle */ void rbl_dns_set_query_start(RBL *rbl, int (*func)(void *, int, unsigned char *, unsigned char *, size_t, void **)) { assert(rbl != NULL); rbl->rbl_dns_start = func; } /* ** RBL_DNS_SET_QUERY_CANCEL -- stores a pointer to a query cancel function ** ** Parameters: ** rbl -- RBL library handle ** func -- function to use to cancel running queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- query handle to be canceled */ void rbl_dns_set_query_cancel(RBL *rbl, int (*func)(void *, void *)) { assert(rbl != NULL); rbl->rbl_dns_cancel = func; } /* ** RBL_DNS_SET_QUERY_WAITREPLY -- stores a pointer to wait for a DNS reply ** ** Parameters: ** rbl -- RBL library handle ** func -- function to use to wait for a reply ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- handle of query that has completed ** struct timeval *timeout -- how long to wait ** size_t *bytes -- bytes returned ** int *error -- error code returned ** int *dnssec -- DNSSEC status returned */ void rbl_dns_set_query_waitreply(RBL *rbl, int (*func)(void *, void *, struct timeval *, size_t *, int *, int *)) { assert(rbl != NULL); rbl->rbl_dns_waitreply = func; } /* ** RBL_DNS_SET_NSLIST -- stores a pointer to a NS list update function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to update NS list ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *dns -- DNS service handle ** const char *nslist -- comma-separated list of nameservers */ void rbl_dns_set_nslist(RBL *lib, int (*func)(void *, const char *)) { assert(lib != NULL); if (func != NULL) lib->rbl_dns_setns = func; else lib->rbl_dns_setns = rbl_res_nslist; } /* ** RBL_DNS_SET_CONFIG -- stores a pointer to a resolver configuration update ** function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to update resolver configuration ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *dns -- DNS service handle ** const char *config -- arbitrary resolver configuration data */ void rbl_dns_set_config(RBL *lib, int (*func)(void *, const char *)) { assert(lib != NULL); lib->rbl_dns_config = func; } /* ** RBL_DNS_SET_TRUSTANCHOR -- stores a pointer to a trust anchor update ** function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to update trust anchor data ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *dns -- DNS service handle ** const char *trust -- arbitrary trust anchor data */ void rbl_dns_set_trustanchor(RBL *lib, int (*func)(void *, const char *)) { assert(lib != NULL); lib->rbl_dns_trustanchor = func; } /* ** RBL_DNS_SET_CLOSE -- stores a pointer to a resolver shutdown function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns void ** void *srv -- DNS service handle */ void rbl_dns_set_close(RBL *lib, void (*func)(void *)) { assert(lib != NULL); if (func != NULL) lib->rbl_dns_close = func; else lib->rbl_dns_close = rbl_res_close; } /* ** RBL_DNS_SET_INIT -- stores a pointer to a resolver init function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void **srv -- DNS service handle (updated) */ void rbl_dns_set_init(RBL *lib, int (*func)(void **)) { assert(lib != NULL); lib->rbl_dns_init = func; } /* ** RBL_DNS_NSLIST -- requests update to a nameserver list ** ** Parameters: ** lib -- RBL library handle ** nslist -- comma-separated list of nameservers to use ** ** Return value: ** An RBL_STAT_* constant. */ RBL_STAT rbl_dns_nslist(RBL *lib, const char *nslist) { int status; assert(lib != NULL); assert(nslist != NULL); if (lib->rbl_dns_setns != NULL) { status = lib->rbl_dns_setns(lib->rbl_dns_service, nslist); if (status != 0) return RBL_STAT_ERROR; } return RBL_STAT_OK; } /* ** RBL_DNS_CONFIG -- requests a change to resolver configuration ** ** Parameters: ** lib -- RBL library handle ** config -- opaque configuration string ** ** Return value: ** An RBL_STAT_* constant. */ RBL_STAT rbl_dns_config(RBL *lib, const char *config) { int status; assert(lib != NULL); assert(config != NULL); if (lib->rbl_dns_config != NULL) { status = lib->rbl_dns_config(lib->rbl_dns_service, config); if (status != 0) return RBL_STAT_ERROR; } return RBL_STAT_OK; } /* ** RBL_DNS_TRUSTANCHOR -- requests a change to resolver trust anchor data ** ** Parameters: ** lib -- RBL library handle ** trust -- opaque trust anchor string ** ** Return value: ** An RBL_STAT_* constant. */ RBL_STAT rbl_dns_trustanchor(RBL *lib, const char *trust) { int status; assert(lib != NULL); assert(trust != NULL); if (lib->rbl_dns_trustanchor != NULL) { status = lib->rbl_dns_trustanchor(lib->rbl_dns_service, trust); if (status != 0) return RBL_STAT_ERROR; } return RBL_STAT_OK; } /* ** RBL_DNS_INIT -- force nameserver (re)initialization ** ** Parameters: ** lib -- RBL library handle ** ** Return value: ** An RBL_STAT_* constant. */ RBL_STAT rbl_dns_init(RBL *lib) { int status; assert(lib != NULL); if (lib->rbl_dns_service != NULL && lib->rbl_dns_close != NULL) lib->rbl_dns_close(lib->rbl_dns_service); lib->rbl_dns_service = NULL; if (lib->rbl_dns_init != NULL) return lib->rbl_dns_init(&lib->rbl_dns_service); else return RBL_STAT_OK; } /* ** RBL_QUERY_CANCEL -- cancel an open query to the RBL ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** qh -- query handle ** ** Return value: ** RBL_STAT_* -- as defined */ RBL_STAT rbl_query_cancel(RBL *rbl, void *qh) { struct rbl_query *rq; assert(rbl != NULL); assert(qh != NULL); rq = qh; rbl->rbl_dns_cancel(rbl->rbl_dns_service, rq->rq_qh); if (rbl->rbl_free != NULL) rbl->rbl_free(rbl->rbl_closure, rq); else free(rq); return RBL_STAT_OK; } /* ** RBL_QUERY_START -- initiate a query to the RBL for entries ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** query -- query string ** qh -- query handle (returned) ** ** Return value: ** RBL_STAT_* -- as defined */ RBL_STAT rbl_query_start(RBL *rbl, u_char *query, void **qh) { int status; struct rbl_query *rq; u_char rblquery[RBL_MAXHOSTNAMELEN + 1]; assert(rbl != NULL); assert(query != NULL); assert(qh != NULL); if (rbl->rbl_qroot[0] == '\0') { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "query root not set"); return RBL_STAT_INVALID; } snprintf(rblquery, sizeof rblquery, "%s.%s", query, rbl->rbl_qroot); if (rbl->rbl_malloc != NULL) rq = rbl->rbl_malloc(rbl->rbl_closure, sizeof(*rq)); else rq = malloc(sizeof(*rq)); if (rq == NULL) return RBL_STAT_NORESOURCE; memset(rq, '\0', sizeof *rq); if (rbl->rbl_dns_service == NULL && rbl->rbl_dns_init != NULL && rbl->rbl_dns_init(&rbl->rbl_dns_service) != 0) { if (rbl->rbl_free != NULL) rbl->rbl_free(rbl->rbl_closure, rq); else free(rq); return RBL_STAT_DNSERROR; } status = rbl->rbl_dns_start(rbl->rbl_dns_service, T_A, rblquery, rq->rq_buf, sizeof rq->rq_buf, &rq->rq_qh); if (status == 0) { *qh = rq; return RBL_STAT_OK; } else { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "unable to start query for '%s'", rblquery); return RBL_STAT_DNSERROR; } } /* ** RBL_QUERY_CHECK -- check for a reply from an active query ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** qh -- query handle (returned) ** timeout -- timeout ** res -- 32-bit buffer into which to write the result (can be NULL) ** ** Return value: ** RBL_STAT_* -- as defined */ RBL_STAT rbl_query_check(RBL *rbl, void *qh, struct timeval *timeout, uint32_t *res) { int dnserr; int status; int n; int type; int class; int qdcount; int ancount; struct rbl_query *rq; u_char *cp; u_char *eom; u_char *found = NULL; HEADER hdr; u_char qname[RBL_MAXHOSTNAMELEN + 1]; assert(rbl != NULL); assert(qh != NULL); rq = qh; status = rbl->rbl_dns_waitreply(rbl->rbl_dns_service, rq->rq_qh, timeout, &rq->rq_anslen, &dnserr, NULL); if (status == RBL_DNS_ERROR) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "error during query"); return RBL_STAT_ERROR; } else if (status == RBL_DNS_NOREPLY) { return RBL_STAT_NOREPLY; } else if (status == RBL_DNS_EXPIRED) { return RBL_STAT_EXPIRED; } /* set up pointers */ memcpy(&hdr, rq->rq_buf, sizeof hdr); cp = (u_char *) rq->rq_buf + HFIXEDSZ; eom = (u_char *) rq->rq_buf + rq->rq_anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) rq->rq_buf, eom, cp, (char *) qname, sizeof qname); if ((n = dn_skipname(cp, eom)) < 0) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_A || class != C_IN) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' unexpected reply type/class", qname); return RBL_STAT_ERROR; } /* if NXDOMAIN, return DKIM_STAT_NOKEY */ if (hdr.rcode == NXDOMAIN) return RBL_STAT_NOTFOUND; /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) return RBL_STAT_NOTFOUND; /* ** Extract the data from the first TXT answer. */ while (--ancount >= 0 && cp < eom) { /* grab the label, even though we know what we asked... */ if ((n = dn_expand((unsigned char *) rq->rq_buf, eom, cp, (RES_UNC_T) qname, sizeof qname)) < 0) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } GETSHORT(type, cp); GETSHORT(class, cp); /* skip the TTL */ cp += INT32SZ; /* skip CNAME if found; assume it was resolved */ if (type == T_CNAME) { char chost[RBL_MAXHOSTNAMELEN + 1]; n = dn_expand((u_char *) rq->rq_buf, eom, cp, chost, RBL_MAXHOSTNAMELEN); cp += n; continue; } else if (type == T_RRSIG) { /* get payload length */ if (cp + INT16SZ > eom) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } GETSHORT(n, cp); cp += n; continue; } else if (type != T_A) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' unexpected reply type/class", qname); return RBL_STAT_ERROR; } if (found != NULL) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "multiple replies for '%s'", qname); return RBL_STAT_ERROR; } /* remember where this one started */ found = cp; /* get payload length */ if (cp + INT16SZ > eom) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } GETSHORT(n, cp); /* move forward for now */ cp += n; } /* if ancount went below 0, there were no good records */ if (found == NULL) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply was unresolved CNAME", qname); return RBL_STAT_ERROR; } /* come back to the one we found */ cp = found; /* get payload length */ if (cp + INT16SZ > eom) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } GETSHORT(n, cp); if (n != sizeof(uint32_t)) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } if (cp + n > eom) { snprintf(rbl->rbl_error, sizeof rbl->rbl_error, "'%s' reply corrupt", qname); return RBL_STAT_ERROR; } /* extract the payload */ if (res != NULL) { uint32_t addr; GETLONG(addr, cp); *res = addr; } return RBL_STAT_FOUND; } OpenDKIM-rel-opendkim-2-11-0-Beta2/librbl/rbl.h000066400000000000000000000253431337314105200206620ustar00rootroot00000000000000/* ** Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. */ #ifndef _RBL_H_ #define _RBL_H_ /* system includes */ #include #include #ifdef HAVE_STDINT_H # include #endif /* HAVE_STDINT_H */ /* definitions */ #define RBL_DEFTIMEOUT 5 #define RBL_MAXHOSTNAMELEN 256 #define RBL_MAXERRORSTRING 256 /* return codes */ typedef int RBL_STAT; #define RBL_STAT_ERROR (-1) #define RBL_STAT_OK 0 #define RBL_STAT_INVALID 1 #define RBL_STAT_DNSERROR 2 #define RBL_STAT_NORESOURCE 3 #define RBL_STAT_NOTIMPLEMENT 4 #define RBL_STAT_NOTFOUND 5 #define RBL_STAT_FOUND 6 /* reply available */ #define RBL_STAT_NOREPLY 7 /* reply not available (yet) */ #define RBL_STAT_EXPIRED 8 /* no reply, query expired */ /* generic DNS error codes */ #define RBL_DNS_ERROR (-1) /* error in transit */ #define RBL_DNS_SUCCESS 0 /* reply available */ #define RBL_DNS_NOREPLY 1 /* reply not available (yet) */ #define RBL_DNS_EXPIRED 2 /* no reply, query expired */ /* types */ struct rbl_handle; typedef struct rbl_handle RBL; /* prototypes */ /* ** RBL_INIT -- initialize an RBL handle ** ** Parameters: ** caller_mallocf -- caller-provided memory allocation function ** caller_freef -- caller-provided memory release function ** closure -- memory closure to pass to the above when used ** ** Return value: ** A new RBL handle suitable for use with other RBL functions, or ** NULL on failure. ** ** Side effects: ** Strange radar returns at Indianapolis ARTCC. */ extern RBL * rbl_init __P((void *(*caller_mallocf)(void *closure, size_t nbytes), void (*caller_freef)(void *closure, void *p), void *closure)); /* ** RBL_CLOSE -- shut down a RBL instance ** ** Parameters: ** rbl -- RBL handle to shut down ** ** Return value: ** None. */ extern void rbl_close __P((RBL *)); /* ** RBL_GETERROR -- return any stored error string from within the RBL ** context handle ** ** Parameters: ** rbl -- RBL handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ extern const u_char *rbl_geterror __P((RBL *)); /* ** RBL_SETDOMAIN -- declare the RBL's domain (the query root) ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** qroot-- certifiers string ** ** Return value: ** None (yet). */ extern void rbl_setdomain __P((RBL *, u_char *)); /* ** RBL_QUERY_START -- initiate a query to the RBL for entries ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** query -- query string ** qh -- query handle (returned) ** ** Return value: ** RBL_STAT_INVALID -- rbl_setdomain() was not called, or "query" was NULL ** RBL_STAT_* -- as defined */ extern RBL_STAT rbl_query_start __P((RBL *, u_char *, void **)); /* ** RBL_QUERY_CHECK -- check for a reply from an active query ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** qh -- query handle (returned) ** timeout -- timeout ** res -- 32-bit buffer into which to write the result (can be NULL) ** ** Return value: ** RBL_STAT_* -- as defined */ extern RBL_STAT rbl_query_check __P((RBL *, void *, struct timeval *, uint32_t *)); /* ** RBL_QUERY_CANCEL -- cancel an open query to the RBL ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** qh -- query handle ** ** Return value: ** RBL_STAT_* -- as defined */ extern RBL_STAT rbl_query_cancel __P((RBL *, void *)); /* ** RBL_SETTIMEOUT -- set the DNS timeout ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** timeout -- requested timeout (seconds) ** ** Return value: ** None. */ extern void rbl_settimeout __P((RBL *, u_int)); /* ** RBL_SETCALLBACKINT -- set the DNS callback interval ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** cbint -- requested callback interval (seconds) ** ** Return value: ** None. */ extern void rbl_setcallbackint __P((RBL *, u_int)); /* ** RBL_SETCALLBACKCTX -- set the DNS callback context ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** ctx -- context to pass to the DNS callback ** ** Return value: ** None. */ extern void rbl_setcallbackctx __P((RBL *, void *)); /* ** RBL_SETDNSCALLBACK -- set the DNS wait callback ** ** Parameters: ** rbl -- RBL handle, created by rbl_init() ** func -- function to call; should take an opaque context pointer ** ** Return value: ** None. */ extern void rbl_setdnscallback __P((RBL *rbl, void (*func)(const void *context))); /* ** RBL_DNS_SET_QUERY_SERVICE -- stores a handle representing the DNS ** query service to be used, returning any ** previous handle ** ** Parameters: ** rbl -- RBL library handle ** h -- handle to be used ** ** Return value: ** Previously stored handle, or NULL if none. */ extern void *rbl_dns_set_query_service __P((RBL *, void *)); /* ** RBL_DNS_SET_QUERY_START -- stores a pointer to a query start function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to start queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- receives handle stored by ** rbl_dns_set_query_service() ** int type -- DNS RR query type (C_IN assumed) ** char *query -- question to ask ** char *buf -- buffer into which to write reply ** size_t buflen -- size of buf ** void **qh -- returned query handle */ extern void rbl_dns_set_query_start __P((RBL *, int (*)(void *, int, unsigned char *, unsigned char *, size_t, void **))); /* ** RBL_DNS_SET_QUERY_CANCEL -- stores a pointer to a query cancel function ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to cancel running queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- query handle to be canceled */ extern void rbl_dns_set_query_cancel __P((RBL *, int (*)(void *, void *))); /* ** RBL_DNS_SET_QUERY_WAITREPLY -- stores a pointer to wait for a DNS reply ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to wait for a reply ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- handle of query that has completed ** struct timeval *timeout -- how long to wait ** size_t *bytes -- bytes returned ** int *error -- error code returned ** int *dnssec -- DNSSEC status returned */ extern void rbl_dns_set_query_waitreply __P((RBL *, int (*)(void *, void *, struct timeval *, size_t *, int *, int *))); /* ** RBL_DNS_SET_NSLIST -- set function that updates resolver nameserver list ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to update the nameserver list ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *srv -- DNS service handle ** const char *nslist -- nameserver list, as a comma-separated ** string */ extern void rbl_dns_set_nslist __P((RBL *, int (*)(void *, const char *))); /* ** RBL_DNS_SET_CLOSE -- shuts down the resolver ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to shut down the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns void ** void *srv -- DNS service handle */ extern void rbl_dns_set_close __P((RBL *, void (*)(void *))); /* ** RBL_DNS_SET_INIT -- initializes the resolver ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void **srv -- DNS service handle (updated) */ extern void rbl_dns_set_init __P((RBL *, int (*)(void **))); /* ** RBL_DNS_SET_CONFIG -- configures the resolver ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to configure the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *srv -- DNS service handle ** const char *config -- arbitrary resolver configuration data */ extern void rbl_dns_set_config __P((RBL *, int (*)(void *, const char *))); /* ** RBL_DNS_SET_TRUSTANCHOR -- provides trust anchor data to the resolver ** ** Parameters: ** lib -- RBL library handle ** func -- function to use to pass trust anchor data to the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *srv -- DNS service handle ** const char *trust -- arbitrary trust anchor data */ extern void rbl_dns_set_trustanchor __P((RBL *, int (*)(void *, const char *))); /* ** RBL_DNS_NSLIST -- requests update to a nameserver list ** ** Parameters: ** lib -- RBL library handle ** nslist -- comma-separated list of nameservers to use ** ** Return value: ** An RBL_STAT_* constant. */ extern RBL_STAT rbl_dns_nslist __P((RBL *, const char *)); /* ** RBL_DNS_CONFIG -- requests a change to resolver configuration ** ** Parameters: ** lib -- RBL library handle ** config -- opaque configuration string ** ** Return value: ** An RBL_STAT_* constant. */ extern RBL_STAT rbl_dns_config __P((RBL *, const char *)); /* ** RBL_DNS_TRUSTANCHOR -- requests a change to resolver trust anchor data ** ** Parameters: ** lib -- RBL library handle ** trust -- opaque trust anchor string ** ** Return value: ** An RBL_STAT_* constant. */ extern RBL_STAT rbl_dns_trustanchor __P((RBL *, const char *)); /* ** RBL_DNS_INIT -- force nameserver (re)initialization ** ** Parameters: ** lib -- RBL library handle ** ** Return value: ** An RBL_STAT_* constant. */ extern RBL_STAT rbl_dns_init __P((RBL *)); #endif /* _RBL_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/librbl/rbl.pc.in000066400000000000000000000005721337314105200214370ustar00rootroot00000000000000# Process this file with autoconf to produce a pkg-config metadata file. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: RBL (Real-time Blacklist) library Description: Library for assisting in RBL query functions URL: http://www.opendkim.org Version: @VERSION@ Libs: -L${libdir} -lrbl Libs.private: @LIBRESOLV@ Cflags: -I${includedir} OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/000077500000000000000000000000001337314105200175745ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/.gitignore000066400000000000000000000000451337314105200215630ustar00rootroot00000000000000ut ut.o ut.core Makefile.in Makefile OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/Makefile.am000066400000000000000000000005601337314105200216310ustar00rootroot00000000000000# Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. # lib_LTLIBRARIES = libut.la libut_la_SOURCES = ut.c libut_la_LDFLAGS = -version-info 1:0:0 libutincludedir = $(includedir)/ut libutinclude_HEADERS = ut.h if RPATH libut_la_LDFLAGS += -rpath $(libdir) endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = ut.pc dist_man_MANS = ut.3 OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/ut.3000066400000000000000000000041761337314105200203200ustar00rootroot00000000000000.TH libut 3 .SH NAME .B ut_init(), ut_destroy(), ut_keyvalue(), ut_generate() \- URI template facility .SH SYNOPSIS #include .I URITEMP * .B ut_init (void); void .B ut_destroy (URITEMP *ut); int .B ut_keyvalue (URITEMP *ut, int type, const char *name, void *value); size_t .B ut_generate (URITEMP *ut, const char *template, char *buf, size_t buflen); .SH DESCRIPTION These functions provide a mechanism to generate Universal Resource Identifiers (URIs) based on a provided template. An application first initializes a template using .B ut_init(), which returns a handle. Then, via multiple calls to .B ut_keyvalue(), values are assigned to symbolic names which are then registered with the handle. A name may reference a string, a list of strings, or a set of key-value pairs. After registration is complete, .B ut_generate() is used to generate a URI based on a provided template. When the handle is no longer needed, .B ut_destroy() is used to deallocate resources associated with the handle. The .I type parameter to .B ut_keyvalue() must be one of UT_KEYTYPE_STRING, UT_KEYTYPE_LIST or UT_KEYTYPE_KEYVALUE. If it is UT_KEYTYPE_LIST, the .I value parameter should be a NULL-terminated array of terminated strings that comprise the list; if it us UT_KEYTYPE_KEYVALUE, the .I value parameter should be a NULL-terminated array of terminated strings where the even-numbered entries are keys and odd-numbered entries are their corresponding values. It returns 0 on success or non-zero on error. If the .I name was already in use, its value(s) are replaced. The .I template parameter to .B ut_generate() is expected to conform to the URI templates draft (see below). The .I buf parameter points to a buffer where the result will be written, up to .I buflen bytes. The buffer will always remain properly terminated. The function returns the number of bytes that would be needed to expand the template completely, or a negative number on error. Thus, if the return value exceeds .I buflen, the string produced was truncated. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO draft-gregorio-uritemplate OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/ut.c000066400000000000000000000722141337314105200203760ustar00rootroot00000000000000/* ** Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. */ /* system includes */ #include #include #include #include #include #include #include /* libut includes */ #include "ut.h" /* types */ struct ut_keyvalue { int ukv_type; const char * ukv_key; void * ukv_value; struct ut_keyvalue * ukv_next; }; struct uri_template { struct ut_keyvalue * ut_params; struct ut_keyvalue * ut_paramstail; }; #define UT_GEN_DELIM(x) ((x) == ':' || \ (x) == '/' || \ (x) == '?' || \ (x) == '#' || \ (x) == '[' || \ (x) == ']' || \ (x) == '@') #define UT_SUB_DELIM(x) ((x) == '!' || \ (x) == '$' || \ (x) == '&' || \ (x) == '\'' || \ (x) == '(' || \ (x) == ')' || \ (x) == '*' || \ (x) == '+' || \ (x) == ',' || \ (x) == ';' || \ (x) == ';' || \ (x) == '=') #define UT_UNRESERVED(x) (isalpha(x) || isdigit(x) || \ (x) == '-' || \ (x) == '.' || \ (x) == '_' || \ (x) == '~') #define UT_RESERVED(x) (UT_GEN_DELIM(x) || UT_SUB_DELIM(x)) #define UT_OP_RESERVE(x) ((x) == '=' || \ (x) == ',' || \ (x) == '!' || \ (x) == '@' || \ (x) == '|') #define UT_OPERATOR(x) ((x) == '+' || \ (x) == '#' || \ (x) == '.' || \ (x) == '/' || \ (x) == ';' || \ (x) == '?' || \ (x) == '&' || \ UT_OP_RESERVE(x)) #define UT_VARCHAR(x) (isalpha(*x) || \ isdigit(*x) || \ (*x) == '_' || \ ut_pct_encoded(x)) #define UT_ALLOW_U 1 #define UT_ALLOW_UR 2 /* ** UT_HEXDIGIT -- hexadecimal digit conversion ** ** Parameters: ** c -- character to convert ** ** Return value: ** Decimal equivalent, or 0 on error. */ static int ut_hexdigit(int c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'F') return c - 'A' + 10; else if (c >= 'a' && c <= 'f') return c - 'a' + 10; else return 0; } /* ** UT_PCT_ENCODED -- determine whether or not a pct-encoded byte has ** been encoutered ** ** Parameters: ** p -- string to scan ** ** Return value: ** 1 iff "p" points to something "pct-encoded" */ static int ut_pct_encoded(const char *p) { assert(p != NULL); return (*p == '%' && isxdigit(*(p + 1)) && isxdigit(*(p + 2))); } /* ** UT_VALID_VARNAME -- confirm a valid varname ** ** Parameters: ** s -- string to check ** ** Return value: ** 1 iff "s" points to a valid varname */ static int ut_valid_varname(const char *s) { char *p; assert(s != NULL); if (!UT_VARCHAR(&s[0])) return 0; for (p = (char *) &s[1]; *p != '\0'; p++) { if (*p != '.' && !UT_VARCHAR(p)) return 0; } return 1; } /* ** UT_FREE -- free a key-value node and its descendents ** ** Parameters: ** kv -- a key-value node ** ** Return value: ** None. */ static void ut_free(struct ut_keyvalue *kv) { assert(kv != NULL); if (kv->ukv_type == UT_KEYTYPE_STRING) { free((void *) kv->ukv_key); if (kv->ukv_value != NULL) free(kv->ukv_value); } else if (kv->ukv_type == UT_KEYTYPE_LIST || kv->ukv_type == UT_KEYTYPE_KEYVALUE) { struct ut_keyvalue *next; struct ut_keyvalue *tmp; tmp = kv->ukv_value; while (tmp != NULL) { free((void *) tmp->ukv_key); if (tmp->ukv_value != NULL) free(tmp->ukv_value); next = tmp->ukv_next; free(tmp); tmp = next; } } free(kv); } /* ** UT_FINDKEY -- locate a key in a URI template handle ** ** Parameters: ** ut -- URITEMP handle ** key -- key to find ** ** Return value: ** Pointer to a (struct ut_keyvalue) node, or NULL if not found. */ static struct ut_keyvalue * ut_findkey(URITEMP ut, const char *key) { struct ut_keyvalue *find; for (find = ut->ut_params; find != NULL; find = find->ukv_next) { if (strcasecmp(find->ukv_key, key) == 0) return find; } return NULL; } /* ** UT_APPEND -- append a string, encoding as needed ** ** Parameters: ** ap -- append point ** rem -- bytes available at "ap" ** allow -- allowed characters ** in -- input string ** maxlen -- max length (-1 for unbounded) ** ** Return value: ** Count of bytes appended; may exceed "rem" if truncation occurred */ static size_t ut_append(char *ap, size_t rem, int allow, const char *in, int maxlen) { int encode = 0; size_t out = 0; const char *p; assert(ap != NULL); assert(allow == UT_ALLOW_U || allow == UT_ALLOW_UR); assert(in != NULL); for (p = in; *p != '\0'; p++) { if (allow == UT_ALLOW_U && !UT_UNRESERVED(*p)) encode = 1; else if (allow == UT_ALLOW_UR && !(UT_UNRESERVED(*p) || UT_RESERVED(*p) || ut_pct_encoded(p))) encode = 1; else encode = 0; if (encode) { (void) snprintf(ap, rem, "%%%02X", *p); ap += 3; rem -= 3; out += 3; } else { *ap++ = *p; rem--; out++; } if (maxlen > 0) { maxlen--; if (maxlen <= 0) break; } } return out; } /* ** UT_INIT -- initialize a URI template handle ** ** Parameters: ** None. ** ** Return value: ** None. */ URITEMP ut_init(void) { struct uri_template *new; new = malloc(sizeof *new); if (new != NULL) memset(new, '\0', sizeof *new); return new; } /* ** UT_DESTROY -- release a URI template handle and all allocated resources ** associated with it ** ** Parameters: ** ut -- URITEMP handle previously allocated by ut_init() ** ** Return value: ** None. */ void ut_destroy(URITEMP ut) { assert(ut != NULL); struct ut_keyvalue *kv; struct ut_keyvalue *tmp; kv = ut->ut_params; while (kv != NULL) { tmp = kv->ukv_next; ut_free(kv); kv = tmp; } free(ut); } /* ** UT_KEYVALUE -- set a key-value of some kind inside a URI template ** ** Parameters: ** ut -- URITEMP handle previously returned by ut_init(); ** ** Return value: ** 0 -- success ** !0 -- error */ int ut_keyvalue(URITEMP ut, int type, const char *key, void *value) { int c; const char **strings; struct ut_keyvalue *kv; struct ut_keyvalue *prev; struct ut_keyvalue *new; struct ut_keyvalue *child; struct ut_keyvalue *head; struct ut_keyvalue *tail; assert(ut != NULL); assert(key != NULL); assert(value != NULL); assert(type == UT_KEYTYPE_STRING || type == UT_KEYTYPE_LIST || type == UT_KEYTYPE_KEYVALUE); /* see if we have it already */ prev = NULL; kv = ut->ut_params; while (kv != NULL) { if (strcasecmp(key, kv->ukv_key) == 0) { if (prev != NULL) { prev->ukv_next = kv->ukv_next; if (kv == ut->ut_paramstail) ut->ut_paramstail = prev; ut_free(kv); kv = prev; } else { ut->ut_params = kv->ukv_next; if (kv == ut->ut_paramstail) ut->ut_paramstail = prev; ut_free(kv); kv = ut->ut_params; } break; } prev = kv; kv = kv->ukv_next; } /* store the new one */ new = malloc(sizeof *new); if (new == NULL) return -1; memset(new, '\0', sizeof *new); new->ukv_type = type; new->ukv_key = strdup(key); if (new->ukv_key == NULL) { free(new); return -1; } switch (type) { case UT_KEYTYPE_STRING: new->ukv_value = strdup((char *) value); if (new->ukv_value == NULL) { free((void *) new->ukv_key); free(new); return -1; } break; case UT_KEYTYPE_LIST: strings = (const char **) value; head = NULL; tail = NULL; for (c = 0; strings[c] != NULL; c++) { child = malloc(sizeof *child); if (child == NULL) { ut_free(new); return -1; } memset(child, '\0', sizeof *child); child->ukv_key = strdup(strings[c]); if (child->ukv_key == NULL) { ut_free(new); return -1; } if (head == NULL) { head = child; tail = child; } else { tail->ukv_next = child; tail = child; } } new->ukv_value = head; break; case UT_KEYTYPE_KEYVALUE: strings = (const char **) value; head = NULL; tail = NULL; for (c = 0; strings[c] != NULL; c++) { if (c % 2 == 0) { child = malloc(sizeof *child); if (child == NULL) { ut_free(new); return -1; } memset(child, '\0', sizeof *child); child->ukv_key = strdup(strings[c]); if (child->ukv_key == NULL) { ut_free(new); return -1; } } else { child->ukv_value = strdup(strings[c]); if (child->ukv_value == NULL) { ut_free(new); return -1; } } if (c % 2 == 1) { if (head == NULL) { head = child; tail = child; } else { tail->ukv_next = child; tail = child; } } } if (c % 2 != 0) { ut_free(new); return -1; } new->ukv_value = head; break; default: /* inconceivable! */ return -1; } new->ukv_type = type; if (ut->ut_params == NULL) { ut->ut_params = new; ut->ut_paramstail = new; } else { ut->ut_paramstail->ukv_next = new; ut->ut_paramstail = new; } return 0; } /* ** UT_GENERATE -- generate a URI based on a template and some values ** ** Parameters: ** ut -- URITEMP template previously initialized with ut_init() ** template -- input template ** out -- output buffer ** outlen -- bytes available at "out" ** ** Return value: ** < 0 -- error (see error codes) ** otherwise -- length of the generated string; if larger than "outlen", ** truncation has occurred ** ** Notes: ** "out" is always properly terminated. ** ** This doesn't support UTF-8 encoding yet. */ size_t ut_generate(URITEMP ut, const char *template, char *out, size_t outlen) { char op; unsigned int maxlen; int firstout; int named; int error = UT_ERROR_OK; int allow; int lsep; size_t alen; size_t rem; size_t olen = 0; size_t vlistlen = 0; const char *p; char *q; char *eb; char *sep; char *first; char *ifemp; char *v; char *ctx; char *vlist; char *colon; char *explode; struct ut_keyvalue *ukv; assert(ut != NULL); assert(template != NULL); assert(out != NULL); rem = outlen - 1; memset(out, '\0', outlen); q = out; for (p = template; *p != '\0'; p++) { if (error != 0) { if (rem > 0) { *q = *p; q++; rem--; } olen++; continue; } if (UT_UNRESERVED(*p) || UT_RESERVED(*p)) { if (rem > 0) *q = *p; rem--; q++; olen++; continue; } else if (ut_pct_encoded(p)) { char c; c = 16 * ut_hexdigit(*(p + 1)) + ut_hexdigit(*(p + 2)); *q++ = c; olen++; rem--; p += 2; continue; } else if (*p == '{') { eb = strchr(p, '}'); if (eb == NULL) { *q++ = '{'; rem--; error = UT_ERROR_MALFORMED; continue; } vlistlen = eb - p; p++; if (*p == '}' || (!UT_OPERATOR(*p) && !UT_VARCHAR(p))) { *q++ = '{'; rem--; *q++ = *p; rem--; error = UT_ERROR_MALFORMED; continue; } op = *p; firstout = 0; switch (op) { case '.': first = "."; sep = "."; named = 0; ifemp = ""; allow = UT_ALLOW_U; p++; vlistlen--; break; case '/': first = "/"; sep = "/"; named = 0; ifemp = ""; allow = UT_ALLOW_U; p++; vlistlen--; break; case ';': first = ";"; sep = ";"; named = 1; ifemp = ""; allow = UT_ALLOW_U; p++; vlistlen--; break; case '?': first = "?"; sep = "&"; named = 1; ifemp = "="; allow = UT_ALLOW_U; p++; vlistlen--; break; case '&': first = "&"; sep = "&"; named = 1; ifemp = "="; allow = UT_ALLOW_U; p++; vlistlen--; break; case '#': first = "#"; sep = ","; named = 0; ifemp = ""; allow = UT_ALLOW_UR; p++; vlistlen--; break; case '+': first = ""; sep = ","; named = 0; ifemp = ""; allow = UT_ALLOW_UR; p++; vlistlen--; break; default: first = ""; sep = ","; named = 0; ifemp = ""; allow = UT_ALLOW_U; break; } vlist = strdup(p); vlist[vlistlen - 1] = '\0'; for (v = strtok_r(vlist, ",", &ctx); v != NULL; v = strtok_r(NULL, ",", &ctx)) { colon = strchr(v, ':'); explode = strchr(v, '*'); if (colon != NULL) { *colon = '\0'; maxlen = atoi(colon + 1); } else { maxlen = -1; } if (explode != NULL) *explode = '\0'; ukv = ut_findkey(ut, v); if (ukv == NULL) continue; if (!ut_valid_varname(v)) continue; if (firstout == 0) { if (first[0] != '\0') { if (rem > 0) { *q++ = first[0]; rem--; } olen++; } firstout = 1; } else if (sep[0] != '\0') { if (rem > 0) { *q++ = sep[0]; rem--; } olen++; } switch (ukv->ukv_type) { case UT_KEYTYPE_STRING: if (named == 1) { char *val; alen = ut_append(q, rem, allow, v, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; val = (char *) ukv->ukv_value; if (val == NULL || val[0] == '\0') { if (ifemp[0] != '\0') { if (rem > 0) { *q++ = ifemp[0]; rem--; } olen++; } } else { if (rem > 0) { *q++ = '='; rem--; } olen++; } } if (colon != NULL) { alen = ut_append(q, rem, allow, ukv->ukv_value, maxlen); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; } else { alen = ut_append(q, rem, allow, ukv->ukv_value, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; } break; case UT_KEYTYPE_LIST: if (explode == NULL) { struct ut_keyvalue *ikv; if (named == 1) { alen = ut_append(q, rem, allow, v, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; if (ukv->ukv_value == NULL) { if (ifemp[0] != '\0') { if (rem > 0) { *q++ = ifemp[0]; rem--; } olen++; } } else { if (rem > 0) { *q++ = '='; rem--; } olen++; } } ikv = ukv->ukv_value; lsep = 0; while (ikv != NULL) { if (lsep == 1 && ikv != ukv->ukv_value) { if (rem > 0) { *q++ = ','; rem--; } olen++; } alen = ut_append(q, rem, allow, ikv->ukv_key, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; ikv = ikv->ukv_next; lsep = 1; } } else { struct ut_keyvalue *ikv; ikv = ukv->ukv_value; lsep = 0; while (ikv != NULL) { if (lsep == 1 && ikv != ukv->ukv_value && sep[0] != '\0') { if (rem > 0) { *q++ = sep[0]; rem--; } olen++; } alen = ut_append(q, rem, allow, ikv->ukv_key, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; ikv = ikv->ukv_next; lsep = 1; } } break; case UT_KEYTYPE_KEYVALUE: if (explode == NULL) { struct ut_keyvalue *ikv; if (named == 1) { char *val; alen = ut_append(q, rem, allow, v, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; val = ukv->ukv_value; if (val == NULL) { if (ifemp[0] != '\0') { if (rem > 0) { *q++ = ifemp[0]; rem--; } olen++; } } else { if (rem > 0) { *q++ = '='; rem--; } olen++; } } ikv = ukv->ukv_value; lsep = 0; while (ikv != NULL) { if (lsep == 1 && ikv != ukv->ukv_value) { if (rem > 0) { *q++ = ','; rem--; } olen++; } alen = ut_append(q, rem, allow, ikv->ukv_key, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; if (rem > 0) { *q++ = ','; rem--; } olen++; alen = ut_append(q, rem, allow, ikv->ukv_value, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; lsep = 1; ikv = ikv->ukv_next; } } else { struct ut_keyvalue *ikv; ikv = ukv->ukv_value; lsep = 0; while (ikv != NULL) { if (lsep == 1 && ikv != ukv->ukv_value && sep[0] != '\0') { if (rem > 0) { *q++ = sep[0]; rem--; } olen++; } alen = ut_append(q, rem, allow, ikv->ukv_key, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; if (rem > 0) { *q++ = '='; rem--; } olen++; alen = ut_append(q, rem, allow, ikv->ukv_value, -1); q += alen; if (alen > rem) rem = 0; else rem -= alen; olen += alen; lsep = 1; ikv = ikv->ukv_next; } } break; } } free(vlist); p = eb; } } if (error != UT_ERROR_OK) return error; else return olen; } #ifdef TEST /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ char *listvals[] = { "red", "green", "blue", NULL }; char *keyvals[] = { "semi", ";", "dot", ".", "comma", ",", NULL }; int main(int argc, char **argv) { int status; URITEMP ut; char outbuf[4096]; /* Level 1 examples */ ut = ut_init(); assert(ut != NULL); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "var", "value"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "hello", "Hello World!"); assert(status == 0); status = ut_generate(ut, "{var}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "value") == 0); status = ut_generate(ut, "{hello}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "Hello%20World%21") == 0); ut_destroy(ut); /* Level 2 examples */ ut = ut_init(); assert(ut != NULL); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "var", "value"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "hello", "Hello World!"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "path", "/foo/bar"); assert(status == 0); status = ut_generate(ut, "{+var}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "value") == 0); status = ut_generate(ut, "{+hello}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "Hello%20World!") == 0); status = ut_generate(ut, "{+path}/here", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/foo/bar/here") == 0); status = ut_generate(ut, "here?ref={+path}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "here?ref=/foo/bar") == 0); status = ut_generate(ut, "X{#var}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X#value") == 0); status = ut_generate(ut, "X{#hello}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X#Hello%20World!") == 0); ut_destroy(ut); /* Level 3 examples */ ut = ut_init(); assert(ut != NULL); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "var", "value"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "hello", "Hello World!"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "empty", ""); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "path", "/foo/bar"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "x", "1024"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "y", "768"); assert(status == 0); status = ut_generate(ut, "map?{x,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "map?1024,768") == 0); status = ut_generate(ut, "{x,hello,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "1024,Hello%20World%21,768") == 0); status = ut_generate(ut, "{+x,hello,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "1024,Hello%20World!,768") == 0); status = ut_generate(ut, "{+path,x}/here", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/foo/bar,1024/here") == 0); status = ut_generate(ut, "{#x,hello,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#1024,Hello%20World!,768") == 0); status = ut_generate(ut, "{#path,x}/here", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#/foo/bar,1024/here") == 0); status = ut_generate(ut, "X{.var}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.value") == 0); status = ut_generate(ut, "X{.x,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.1024.768") == 0); status = ut_generate(ut, "{/var}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/value") == 0); status = ut_generate(ut, "{/var,x}/here", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/value/1024/here") == 0); status = ut_generate(ut, "{;x,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";x=1024;y=768") == 0); status = ut_generate(ut, "{;x,y,empty}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";x=1024;y=768;empty") == 0); status = ut_generate(ut, "{?x,y}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?x=1024&y=768") == 0); status = ut_generate(ut, "{?x,y,empty}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?x=1024&y=768&empty=") == 0); status = ut_generate(ut, "?fixed=yes{&x}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?fixed=yes&x=1024") == 0); status = ut_generate(ut, "{&x,y,empty}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "&x=1024&y=768&empty=") == 0); ut_destroy(ut); /* Level 4 examples */ ut = ut_init(); assert(ut != NULL); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "var", "value"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "hello", "Hello World!"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_STRING, "path", "/foo/bar"); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_LIST, "list", listvals); assert(status == 0); status = ut_keyvalue(ut, UT_KEYTYPE_KEYVALUE, "keys", keyvals); assert(status == 0); status = ut_generate(ut, "{var:3}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "val") == 0); status = ut_generate(ut, "{var:30}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "value") == 0); status = ut_generate(ut, "{list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "red,green,blue") == 0); status = ut_generate(ut, "{list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "red,green,blue") == 0); status = ut_generate(ut, "{keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "semi,%3B,dot,.,comma,%2C") == 0); status = ut_generate(ut, "{keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "semi=%3B,dot=.,comma=%2C") == 0); status = ut_generate(ut, "{+path:6}/here", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/foo/b/here") == 0); status = ut_generate(ut, "{+list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "red,green,blue") == 0); status = ut_generate(ut, "{+list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "red,green,blue") == 0); status = ut_generate(ut, "{+keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "semi,;,dot,.,comma,,") == 0); status = ut_generate(ut, "{+keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "semi=;,dot=.,comma=,") == 0); status = ut_generate(ut, "{#path:6*}/here", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#/foo/b/here") == 0); status = ut_generate(ut, "{#list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#red,green,blue") == 0); status = ut_generate(ut, "{#list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#red,green,blue") == 0); status = ut_generate(ut, "{#keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#semi,;,dot,.,comma,,") == 0); status = ut_generate(ut, "{#keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "#semi=;,dot=.,comma=,") == 0); status = ut_generate(ut, "X{.var:3}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.val") == 0); status = ut_generate(ut, "X{.list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.red,green,blue") == 0); status = ut_generate(ut, "X{.list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.red.green.blue") == 0); status = ut_generate(ut, "X{.keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.semi,%3B,dot,.,comma,%2C") == 0); status = ut_generate(ut, "X{.keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "X.semi=%3B.dot=..comma=%2C") == 0); status = ut_generate(ut, "{/var:1,var}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/v/value") == 0); status = ut_generate(ut, "{/list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/red,green,blue") == 0); status = ut_generate(ut, "{/list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/red/green/blue") == 0); status = ut_generate(ut, "{/list*,path:4}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/red/green/blue/%2Ffoo") == 0); status = ut_generate(ut, "{/keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/semi,%3B,dot,.,comma,%2C") == 0); status = ut_generate(ut, "{/keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "/semi=%3B/dot=./comma=%2C") == 0); status = ut_generate(ut, "{;hello:5}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";hello=Hello") == 0); status = ut_generate(ut, "{;list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";list=red,green,blue") == 0); status = ut_generate(ut, "{;list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";red;green;blue") == 0); status = ut_generate(ut, "{;keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";keys=semi,%3B,dot,.,comma,%2C") == 0); status = ut_generate(ut, "{;keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, ";semi=%3B;dot=.;comma=%2C") == 0); status = ut_generate(ut, "{?var:3}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?var=val") == 0); status = ut_generate(ut, "{?list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?list=red,green,blue") == 0); status = ut_generate(ut, "{?list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?red&green&blue") == 0); status = ut_generate(ut, "{?keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?keys=semi,%3B,dot,.,comma,%2C") == 0); status = ut_generate(ut, "{?keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "?semi=%3B&dot=.&comma=%2C") == 0); status = ut_generate(ut, "{&var:3}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "&var=val") == 0); status = ut_generate(ut, "{&list}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "&list=red,green,blue") == 0); status = ut_generate(ut, "{&list*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "&red&green&blue") == 0); status = ut_generate(ut, "{&keys}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "&keys=semi,%3B,dot,.,comma,%2C") == 0); status = ut_generate(ut, "{&keys*}", outbuf, sizeof outbuf); assert(status > 0); assert(strcmp(outbuf, "&semi=%3B&dot=.&comma=%2C") == 0); ut_destroy(ut); return 0; } #endif /* TEST */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/ut.h000066400000000000000000000011671337314105200204020ustar00rootroot00000000000000/* ** Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _UT_H_ #define _UT_H_ /* system includes */ #include #include /* types */ struct uri_template; typedef struct uri_template * URITEMP; #define UT_KEYTYPE_STRING 1 #define UT_KEYTYPE_LIST 2 #define UT_KEYTYPE_KEYVALUE 3 #define UT_ERROR_OK 0 #define UT_ERROR_MALFORMED (-1) /* prototypes */ extern URITEMP ut_init(void); extern void ut_destroy(URITEMP); extern int ut_keyvalue(URITEMP, int, const char *, void *); extern size_t ut_generate(URITEMP, const char *, char *, size_t); #endif /* ! _UT_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libut/ut.pc.in000066400000000000000000000005431337314105200211570ustar00rootroot00000000000000# Process this file with autoconf to produce a pkg-config metadata file. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: UT (URL Template Library) Description: Library for assisting in URI construction from templates URL: http://www.opendkim.org Version: @VERSION@ Libs: -L${libdir} -lut Cflags: -I${includedir} OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/000077500000000000000000000000001337314105200177355ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/.gitignore000066400000000000000000000005511337314105200217260ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure configure.scan aclocal.m4 depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile .deps .libs core *.core OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/Makefile.am000066400000000000000000000006101337314105200217660ustar00rootroot00000000000000# Copyright (c) 2010, 2012, The Trusted Domain Project. All rights reserved. # lib_LTLIBRARIES = libvbr.la libvbr_la_SOURCES = vbr.c libvbr_la_LDFLAGS = -version-info 2:0:0 $(LIBRESOLV) libvbrincludedir = $(includedir)/vbr libvbrinclude_HEADERS = vbr.h if RPATH libvbr_la_LDFLAGS += -rpath $(libdir) endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = vbr.pc dist_man_MANS = vbr.3 OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/vbr.3000066400000000000000000000316051337314105200206170ustar00rootroot00000000000000.TH libvbr 3 .SH NAME .B vbr_init(), vbr_options(), vbr_close(), vbr_geterror(), vbr_getheader(), .B vbr_setcert(), vbr_settype(), vbr_setdomain(), vbr_trustedcerts(), .B vbr_query(), vbr_settimeout(), vbr_setcallbackint(), vbr_setcallbackctx(), .B vbr_setdnscallback(), vbr_dns_set_query_service(), .B vbr_dns_set_query_start(), vbr_dns_set_query_cancel(), .B vbr_dns_set_query_waitreply(), vbr_dns_set_query_waitreply(), .B vbr_dns_set_init(), vbr_dns_set_close(), vbr_dns_set_nslist(), .B vbr_dns_set_config(), vbr_dns_set_trustanchor(), vbr_dns_init() \- Vouch By Reference service facility .SH SYNOPSIS #include .I VBR * .B vbr_init (void *(* .B mallocf )(void *, size_t), void (* .B freef )(void *, void *p), void * .B closure ); void .B vbr_options (VBR * .B vbr , unsigned int .B opts ); unsigned char * .B vbr_geterror (VBR * .B vbr ); VBR_STAT .B vbr_getheader (VBR * .B vbr, unsigned char * .B hdr, size_t .B len ); void .B vbr_setcert (VBR * .B vbr, unsigned char * .B cert ); void .B vbr_settype (VBR * .B vbr, unsigned char * .B cert ); void .B vbr_setdomain (VBR * .B vbr, unsigned char * .B cert ); void .B vbr_trustedcerts (VBR * .B vbr, unsigned char ** .B cert ); VBR_STAT .B vbr_query (VBR * .B vbr, unsigned char ** .B res, unsigned char ** .B cert ); VBR_STAT .B vbr_settimeout (VBR * .B vbr, unsigned int .B timeout ); VBR_STAT .B vbr_setcallbackint (VBR * .B vbr, unsigned int .B cbint ); VBR_STAT .B vbr_setcallbackctx (VBR *, .B vbr, void * .B ctx ); VBR_STAT .B vbr_setdnscallback (VBR *, .B vbr, void (* .B func )(const void *)); void * .B vbr_dns_set_query_service (VBR * .B vbr, void * .B svc ); void .B vbr_dns_set_query_cancel (VBR * .B vbr, int (* .B func )(void *, void *)); void .B vbr_dns_set_query_start (VBR * .B vbr, int (* .B func )(void *, int, unsigned char *, unsigned char *, size_t, void **)); void .B vbr_dns_set_query_waitreply (VBR * .B vbr, int (* .B func )(void *, void *, struct timeval *, size_t *, int *, int *)); void .B vbr_dns_set_init (VBR * .B vbr, int (* .B func )(void **); void .B vbr_dns_set_close (VBR * .B vbr, int (* .B func )(void *); void .B vbr_dns_set_config (VBR * .B vbr, int (* .B func )(void *, const char *); void .B vbr_dns_set_nslist (VBR * .B vbr, int (* .B func )(void *, const char *); void .B vbr_dns_set_trustanchor (VBR * .B vbr, int (* .B func )(void *, const char *); VBR_STAT .B vbr_dns_init (VBR * .B vbr ); void .B vbr_close (VBR *); .SH DESCRIPTION These functions are an interface to a facility to conduct Vouch By Reference (VBR) queries and return their results. VBR is defined in RFC5518. An application first initializes the package by calling .B vbr_init(). The optional .I mallocf parameter is a caller-provided memory allocation function taking a pointer to a caller-provided opaque data structure (the .I closure parameter) and a number of bytes to allocate. If .I mallocf is not provided, the default system memory allocator function .B malloc(3) is used. The optional .I freef parameter specifies a matching caller-provided memory deallocator function, taking a pointer to a caller-provided opaque data structure (the .I closure parameter) and a pointer to the memory to be released. If .I freef is not provided, the default system memory release function .B free(3) is used. A handle for future use of the initialized library instance is returned, or NULL on error and .I errno will be set to indicate the cause of the failure. The caller can use .B vbr_options() to set query processing options. See the OPTIONS section for details. The .B vbr_geterror() function can be used to poll the library for an error string that provides further description for the most recent failed operation. Calling .B vbr_getheader() can be used to generate an RFC-compliant VBR-Info: haeder field based on data provided by other accessor functions, namely .I vbr_setcert(), .I vbr_settype() and .I vbr_setdomain() (below). A library instance is provided as the first parameter, and a pointer to the destination buffer and its length are provided in the second and third. Note that only the value of the header field is stored into the buffer, not its name; the standard name of the header field is available as the VBR_INFOHEADER macro. .B vbr_setcert() takes a VBR library instance as its first argument and a colon-separated list of claimed vouching domains as its second. Similarly, .B vbr_settype() sets the message type, and .B vbr_setdomain() sets the sending domain. These correspond, respectively, to the "mv", "mc" and "md" values from a received message's VBR-Info header field. These values are used by the library instance when calling .I vbr_getheader() to generate VBR information header fields to attach to outgoing messages or when calling .I vbr_query() to check for a vouching reference. Note that the library does no validation of the possible values of the message type (to allow for new message types that may appear outside of the original RFC), and has no context to validate the domain. .B vbr_trustedcerts() takes a VBR library instance as its first argument and a NULL-terminated array of pointers to certifier names as its second, which is used by .I vbr_query() to select vouching services the caller trusts. The intersection of these trusted certifiers and those claimed by an arriving message. The list is initially empty. .B vbr_query() polls trusted certifiers to see if any of them agree with the assertion made by the message sender. The pointer .B res will be set to point to a result string after the query has been resolved. The result will be "pass" if any trusted certifier concurred with the assertion made by the sender. If .B cert is not NULL, it will be updated to point to the name of the trusted certifier that concurred with the sender's assertion when a "pass" result is returned. If any queries were made but none of them resulted in concurrence, a result of "fail" is returned. If no query was made because of errors or because the trusted certifier set and the sender's certifier set included no vouchers in common, .B cert will be unchanged. The .B vbr_settimeout() function can be used to change the query timeout. The default is ten seconds. Note that this timeout is applied for each voucher query, so a call to .I vbr_query() can take longer than this if multiple queries need to be made. If it is useful to have the library periodically call a user-provided function as an indication that queries are still in progress, such a function can be registered with the .B vbr_setdnscallback() function. The function provided should take a void context pointer as its sole argument. .B vbr_setcallbackctx() is used to tell the library what context pointer should be used, and .B vbr_setcallbackint() is used to tell the library what frequency, in seconds, should be used to call that callback function. Each of these takes the corresponding VBR library handle as its first argument, and the obvious parameter for its second. By default, the library will use the stock system resolver to conduct DNS queries. If alternates should be used, these can be specified using the following functions: .B vbr_dns_set_query_service() sets a context pointer to the query service to be used, if any. This will be passed as-is to the other DNS functions. It returns its previous value. .B vbr_dns_set_query_cancel() sets a pointer to the function that should be called to cancel an open query, and should take the following parameters: a void pointer to the DNS query service to be used, and a void pointer to a query handle as previously returned by a call to .I vbr_dns_set_query_start(). The function should return one of the DNS result codes described below. .B vbr_dns_set_query_start() sets a pointer to the function that should be called to initiate a new query, and should take the following parameters: a void pointer to the DNS query service to be used, a DNS record type (e.g. T_TXT), a pointer to a string containing the query to be started, a pointer to a buffer into which the reply should be written, the number of bytes available in that buffer, and a pointer to a void pointer that will be updated to contain a unique handle for that query once started. The function should return one of the DNS result codes described below. .B vbr_dns_set_query_waitreply() sets a pointer to the function that should be called to wait for a reply to an open query, and should take the following parameters: a void pointer to the DNS query service to be used, a void pointer referencing the query of interest as previously returned by a call to .I vbr_dns_set_query_start(), a pointer to a "struct timeval" structure indicating how long the function should wait for a reply (or NULL if infinite waiting is acceptable), a pointer to a "size_t" that will be updated to contain the size of the received reply, a pointer to an integer that will contain an error code if the query fails (can be NULL if that information is not interesting to the caller), and a pointer to an integer that will contain a DNSSEC status indication (can be NULL if that information is not interesting to the caller). The function should return one of the DNS result codes described below. .B vbr_dns_set_init() sets a pointer to the function that should be called when it is necessary to initialize a resolver. The function should store a handle to the initialized resolver and return zero, or return non-zero if initialization could not be completed. .B vbr_dns_set_close() sets a pointer to the function that should be called when it is necessary to terminate a resolver. The function will receive a handle referencing the resolver to be terminated, and should return zero on success or non-zero on failure. .B vbr_dns_set_nslist() sets a pointer to the function that should be called when it is necessary to change the set of nameservers that are to be used to resolve RBL queries. The function will receive a handle referencing the active resolver and a string containing a comma-separated list of nameservers to use. It should return zero on success and non-zero on failure. .B vbr_dns_set_config() sets a pointer to the function that should be called when it is necessary to provide arbitrary configuration information to the resolver. The function will receive a handle referencing the active resolver and a string containing the configuration. It should return zero on success and non-zero on failure. .B vbr_dns_set_trustanchor() sets a pointer to the function that should be called when it is necessary to provide trust anchor information (supporting DNSSEC) to the resolver. The function will receive a handle referencing the active resolver and a string containing the trust anchor data. It should return zero on success and non-zero on failure. Calling .B vbr_dns_init() forces (re-)initialization of the resolver. This essentially causes the library to call any initialization function defined by .B vbr_dns_set_init(). When the library handle is no longer needed, it should be passed to .B vbr_close(). .SH OPTIONS Setting options is done using the .I vbr_options() function. The .I opts parameter is a bitwise-OR list of the available options requested by the application. The currently supported option: .TP .I VBR_FLAG_TRUSTEDONLY By default, a VBR query will be sent to the intersection of the trusted certifiers (provided by the .I vbr_trustedcerts() function) and the list of certifiers claimed on a message (provided by the .I vbr_sercert() function). With this option enabled, the trusted certifiers will be checked and the provided certifiers will be ignored. .SH RETURN VALUES The following return codes, of type VBR_STAT, can be returned: .TP .I VBR_STAT_OK successful completion .TP .I VBR_STAT_INVALID operation failed because an invalid parameter was provided .TP .I VBR_STAT_DNSERROR operation could not be completed because of errors requesting or receiving a DNS reply; note that this does not include a successful reply that contains a "no record found" result, which is a successful answer .TP .I VBR_STAT_NORESOURCE a caller-provided buffer was too small to complete the requested operation, or a memory or file descriptor allocation failed .TP .I VBR_STAT_NOTIMPLEMENT an optional library feature was not selected at compilation time .SH DNS RETURN CODES Any registered DNS functions should return one of the following result codes: .TP .I VBR_DNS_ERROR An error occurred. The cause of the error can be retrieved using .I vbr_geterror(). .TP .I VBR_DNS_SUCCESS The operation was successful. .TP .I VBR_DNS_REPLY A reply is available (returned by the "waitreply" function). .TP .I VBR_DNS_NOREPLY No reply was received by the time the query timeout was reached (returned by the "waitreply" function). .TP .I VBR_DNS_EXPIRED The query expired completely (returned by the "waitreply" function). Some resolvers set an overall timeout for the query at start time in addition to one for each single wait request; this code indicates the former timeout expired. .SH COPYRIGHT Copyright (c) 2010, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I intro(2) OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/vbr.c000066400000000000000000001014511337314105200206740ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. */ /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* ! REENTRANT */ /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef __STDC__ # include #else /* __STDC__ */ # include #endif /* _STDC_ */ /* libvbr includes */ #include "vbr.h" #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #define BUFRSZ 2048 #define DEFERRLEN 64 #define DEFTIMEOUT 10 #define MAXCNAMEDEPTH 3 /* local definitions needed for DNS queries */ #define MAXPACKET 8192 #if defined(__RES) && (__RES >= 19940415) # define RES_UNC_T char * #else /* __RES && __RES >= 19940415 */ # define RES_UNC_T unsigned char * #endif /* __RES && __RES >= 19940415 */ #ifndef T_RRSIG # define T_RRSIG 46 #endif /* ! T_RRSIG */ #define VBR_DNS_ERROR (-1) #define VBR_DNS_SUCCESS 0 #define VBR_DNS_REPLY 1 #define VBR_DNS_NOREPLY 2 #define VBR_DNS_EXPIRED 3 /* struct vbr_query -- an open VBR query */ struct vbr_query { int vq_error; size_t vq_buflen; void * vq_qh; u_char vq_buf[HFIXEDSZ + MAXPACKET]; }; struct vbr_handle { u_int vbr_opts; /* options */ size_t vbr_errlen; /* error buffer size */ u_int vbr_timeout; /* query timeout */ u_int vbr_callback_int; /* callback interval */ void * vbr_user_context; /* user context for callback */ void (*vbr_dns_callback) (const void *); void * (*vbr_malloc) (void *, size_t); void (*vbr_free) (void *, void *); void * vbr_closure; /* memory closure */ u_char * vbr_domain; /* sending domain */ u_char * vbr_type; /* message type */ u_char * vbr_cert; /* claimed certifiers */ u_char * vbr_error; /* error buffer */ u_char ** vbr_trusted; /* trusted certifiers */ void *vbr_dns_service; int (*vbr_dns_start) (void *, int, unsigned char *, unsigned char *, size_t, void **); int (*vbr_dns_cancel) (void *, void *); int (*vbr_dns_init) (void **); void (*vbr_dns_close) (void *); int (*vbr_dns_setns) (void *, const char *); int (*vbr_dns_config) (void *, const char *); int (*vbr_dns_trustanchor) (void *, const char *); int (*vbr_dns_waitreply) (void *, void *, struct timeval *, size_t *, int *, int *); }; /* prototypes */ static void vbr_error __P((VBR *, const char *, ...)); /* ========================= PRIVATE SECTION ========================= */ #if USE_STRL_HCPY == 0 /* ** Copyright (c) 1999-2002, Sendmail Inc. and its suppliers. ** All rights reserved. ** ** By using this file, you agree to the terms and conditions set ** forth in the LICENSE file which can be found at the top level of ** the sendmail distribution. ** ** Copyright (c) 2009, The Trusted Domain Project. All rights reserved. */ /* ** XXX the type of the length parameter has been changed ** from size_t to ssize_t to avoid theoretical problems with negative ** numbers passed into these functions. ** The real solution to this problem is to make sure that this doesn't ** happen, but for now we'll use this workaround. */ #define strlcpy(x,y,z) vbr_strlcpy((x), (y), (z)) /* ** VBR_STRLCPY -- size bounded string copy ** ** This is a bounds-checking variant of strcpy. ** If size > 0, copy up to size-1 characters from the nul terminated ** string src to dst, nul terminating the result. If size == 0, ** the dst buffer is not modified. ** Additional note: this function has been "tuned" to run fast and tested ** as such (versus versions in some OS's libc). ** ** The result is strlen(src). You can detect truncation (not all ** of the characters in the source string were copied) using the ** following idiom: ** ** char *s, buf[BUFSIZ]; ** ... ** if (vbr_strlcpy(buf, s, sizeof(buf)) >= sizeof(buf)) ** goto overflow; ** ** Parameters: ** dst -- destination buffer ** src -- source string ** size -- size of destination buffer ** ** Returns: ** strlen(src) */ size_t vbr_strlcpy(dst, src, size) register char *dst; register const char *src; ssize_t size; { register ssize_t i; if (size-- <= 0) return strlen(src); for (i = 0; i < size && (dst[i] = src[i]) != 0; i++) continue; dst[i] = '\0'; if (src[i] == '\0') return i; else return i + strlen(src + i); } #endif /* USE_STRL_HCPY == 0 */ /* ** VBR_MALLOC -- allocate memory ** ** Parameters: ** vbr -- VBR context in which this is performed ** closure -- opaque closure handle for the allocation ** nbytes -- number of bytes desired ** ** Return value: ** Pointer to allocated memory, or NULL on failure. */ static void * vbr_malloc(VBR *vbr, void *closure, size_t nbytes) { assert(vbr != NULL); if (vbr->vbr_malloc == NULL) return malloc(nbytes); else return vbr->vbr_malloc(closure, nbytes); } /* ** VBR_FREE -- release memory ** ** Parameters: ** vbr -- VBR context in which this is performed ** closure -- opaque closure handle for the allocation ** ptr -- pointer to memory to be freed ** ** Return value: ** None. */ static void vbr_free(VBR *vbr, void *closure, void *ptr) { assert(vbr != NULL); if (vbr->vbr_free == NULL) free(ptr); else vbr->vbr_free(closure, ptr); } /* ** VBR_VERROR -- log an error into a VBR handle (varargs version) ** ** Parameters: ** vbr -- VBR context in which this is performed ** format -- format to apply ** va -- argument list ** ** Return value: ** None. */ static void vbr_verror(VBR *vbr, const char *format, va_list va) { int flen; int saverr; u_char *new; assert(vbr != NULL); assert(format != NULL); saverr = errno; if (vbr->vbr_error == NULL) { vbr->vbr_error = vbr_malloc(vbr, vbr->vbr_closure, DEFERRLEN); if (vbr->vbr_error == NULL) { errno = saverr; return; } vbr->vbr_errlen = DEFERRLEN; } for (;;) { flen = vsnprintf((char *) vbr->vbr_error, vbr->vbr_errlen, format, va); /* compensate for broken vsnprintf() implementations */ if (flen == -1) flen = vbr->vbr_errlen * 2; if (flen >= vbr->vbr_errlen) { new = vbr_malloc(vbr, vbr->vbr_closure, flen + 1); if (new == NULL) { errno = saverr; return; } vbr_free(vbr, vbr->vbr_closure, vbr->vbr_error); vbr->vbr_error = new; vbr->vbr_errlen = flen + 1; } else { break; } } errno = saverr; } /* ** VBR_ERROR -- log an error into a VBR handle ** ** Parameters: ** vbr -- VBR context in which this is performed ** format -- format to apply ** ... -- arguments ** ** Return value: ** None. */ static void vbr_error(VBR *vbr, const char *format, ...) { va_list va; assert(vbr != NULL); assert(format != NULL); va_start(va, format); vbr_verror(vbr, format, va); va_end(va); } /* ** VBR_TIMEOUTS -- do timeout math ** ** Parameters: ** timeout -- general VBR timeout ** ctimeout -- callback timeout ** wstart -- previous wait start time ** wstop -- previous wait stop time ** next -- computed next timeout (updated) ** ** Return value: ** None. */ static void vbr_timeouts(struct timeval *timeout, struct timeval *ctimeout, struct timeval *wstart, struct timeval *wstop, struct timeval **next) { assert(timeout != NULL); assert(ctimeout != NULL); assert(wstart != NULL); assert(wstop != NULL); assert(next != NULL); if (wstop->tv_sec == 0 && wstop->tv_usec == 0) { /* first pass */ if (timeout->tv_sec < ctimeout->tv_sec || (timeout->tv_sec == ctimeout->tv_sec && timeout->tv_usec < ctimeout->tv_usec)) *next = timeout; else *next = ctimeout; } else { struct timeval to1; struct timeval to2; /* compute start through overall timeout */ memcpy(&to1, wstart, sizeof to1); to1.tv_sec += timeout->tv_sec; to1.tv_usec += timeout->tv_usec; if (to1.tv_usec > 1000000) { to1.tv_sec += (to1.tv_usec / 1000000); to1.tv_usec = (to1.tv_usec % 1000000); } /* compute stop through callback timeout */ memcpy(&to2, wstop, sizeof to2); to2.tv_sec += ctimeout->tv_sec; to2.tv_usec += ctimeout->tv_usec; if (to2.tv_usec > 1000000) { to2.tv_sec += (to2.tv_usec / 1000000); to2.tv_usec = (to2.tv_usec % 1000000); } /* ...and decide */ if (to1.tv_sec < to2.tv_sec || (to1.tv_sec == to2.tv_sec && to1.tv_usec < to2.tv_usec)) *next = timeout; else *next = ctimeout; } } /* ** VBR_RES_CANCEL -- cancel a pending resolver query ** ** Parameters: ** srv -- query service handle (ignored) ** qh -- query handle (ignored) ** ** Return value: ** 0 on success, !0 on error ** ** Notes: ** The standard UNIX resolver is synchronous, so in theory this can ** never get called. We have not yet got any use cases for one thread ** canceling another thread's pending queries, so for now just return 0. */ static int vbr_res_cancel(void *srv, void *qh) { if (qh != NULL) free(qh); return 0; } /* ** VBR_RES_QUERY -- initiate a DNS query ** ** Parameters: ** srv -- service handle (ignored) ** type -- RR type to query ** query -- the question to ask ** buf -- where to write the answer ** buflen -- bytes at "buf" ** qh -- query handle, used with vbr_res_waitreply ** ** Return value: ** An VBR_DNS_* constant. ** ** Notes: ** This is a stub for the stock UNIX resolver (res_) functions, which ** are synchronous so no handle needs to be created, so "qh" is set to ** "buf". "buf" is actually populated before this returns (unless ** there's an error). */ static int vbr_res_query(void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh) { int n; int ret; struct vbr_query *vq; unsigned char qbuf[HFIXEDSZ + MAXPACKET]; #ifdef HAVE_RES_NINIT struct __res_state statp; #endif /* HAVE_RES_NINIT */ #ifdef HAVE_RES_NINIT memset(&statp, '\0', sizeof statp); res_ninit(&statp); #endif /* HAVE_RES_NINIT */ #ifdef HAVE_RES_NINIT n = res_nmkquery(&statp, QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf, sizeof qbuf); #else /* HAVE_RES_NINIT */ n = res_mkquery(QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf, sizeof qbuf); #endif /* HAVE_RES_NINIT */ if (n == (size_t) -1) { #ifdef HAVE_RES_NINIT res_nclose(&statp); #endif /* HAVE_RES_NINIT */ return VBR_DNS_ERROR; } #ifdef HAVE_RES_NINIT ret = res_nsend(&statp, qbuf, n, buf, buflen); #else /* HAVE_RES_NINIT */ ret = res_send(qbuf, n, buf, buflen); #endif /* HAVE_RES_NINIT */ if (ret == -1) { #ifdef HAVE_RES_NINIT res_nclose(&statp); #endif /* HAVE_RES_NINIT */ return VBR_DNS_ERROR; } #ifdef HAVE_RES_NINIT res_nclose(&statp); #endif /* HAVE_RES_NINIT */ vq = (struct vbr_query *) malloc(sizeof *vq); if (vq == NULL) return VBR_DNS_ERROR; if (ret == -1) { vq->vq_error = errno; vq->vq_buflen = 0; } else { vq->vq_error = 0; vq->vq_buflen = (size_t) ret; } *qh = (void *) vq; return VBR_DNS_SUCCESS; } /* ** VBR_RES_WAITREPLY -- wait for a reply to a pending query ** ** Parameters: ** srv -- service handle ** qh -- query handle ** to -- timeout ** bytes -- number of bytes in the reply (returned) ** error -- error code (returned) ** ** Return value: ** A VBR_DNS_* code. ** ** Notes: ** Since the stock UNIX resolver is synchronous, the reply was completed ** before vbr_res_query() returned, and thus this is almost a no-op. */ int vbr_res_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec) { struct vbr_query *vq; assert(qh != NULL); vq = qh; if (bytes != NULL) *bytes = vq->vq_buflen; if (error != NULL) *error = vq->vq_error; return VBR_DNS_SUCCESS; } /* ** VBR_TXT_DECODE -- decode a TXT reply ** ** Parameters: ** ansbuf -- answer buffer ** anslen -- size of answer buffer ** buf -- output buffer ** buflen -- size of output buffer ** ** Return value: ** TRUE iff ansbuf contains an IN TXT reply that could be deocde. */ static _Bool vbr_txt_decode(u_char *ansbuf, size_t anslen, u_char *buf, size_t buflen) { int type = -1; int class = -1; int qdcount; int ancount; int n; int c; u_char *cp; u_char *eom; u_char *p; HEADER hdr; char qname[VBR_MAXHOSTNAMELEN + 1]; assert(ansbuf != NULL); assert(buf != NULL); /* set up pointers */ memcpy(&hdr, ansbuf, sizeof hdr); cp = ansbuf + HFIXEDSZ; eom = ansbuf + anslen; /* skip over the name at the front of the answer */ for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand(ansbuf, eom, cp, qname, sizeof qname); if ((n = dn_skipname(cp, eom)) < 0) return FALSE; cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return FALSE; GETSHORT(type, cp); GETSHORT(class, cp); } if (type != T_TXT || class != C_IN) return FALSE; if (hdr.rcode == NXDOMAIN) return FALSE; /* get the answer count */ ancount = ntohs((unsigned short) hdr.ancount); if (ancount == 0) return FALSE; /* if truncated, we can't do it */ if (hdr.tc) return FALSE; /* grab the label, even though we know what we asked... */ if ((n = dn_expand(ansbuf, eom, cp, (RES_UNC_T) qname, sizeof qname)) < 0) return FALSE; /* ...and move past it */ cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return FALSE; GETSHORT(type, cp); GETSHORT(class, cp); /* reject anything that's not valid (stupid wildcards) */ if (type != T_TXT || class != C_IN) return FALSE; /* skip the TTL */ cp += INT32SZ; /* get payload length */ if (cp + INT16SZ > eom) return FALSE; GETSHORT(n, cp); /* XXX -- maybe deal with a partial reply rather than require it all */ if (cp + n > eom) return FALSE; if (n > buflen) return FALSE; /* extract the payload */ memset(buf, '\0', buflen); p = buf; while (n > 0) { c = *cp++; n--; while (c > 0) { *p++ = *cp++; c--; n--; } } return TRUE; } /* ========================= PUBLIC SECTION ========================= */ /* ** VBR_INIT -- initialize a VBR handle ** ** Parameters: ** caller_mallocf -- caller-provided memory allocation function ** caller_freef -- caller-provided memory release function ** closure -- memory closure to pass to the above when used ** ** Return value: ** A new VBR handle suitable for use with other VBR functions, or ** NULL on failure. ** ** Side effects: ** Strange radar returns at Indianapolis ARTCC. */ VBR * vbr_init(void *(*caller_mallocf)(void *closure, size_t nbytes), void (*caller_freef)(void *closure, void *p), void *closure) { VBR *new; /* copy the parameters */ new = (VBR *) malloc(sizeof(struct vbr_handle)); if (new == NULL) return NULL; new->vbr_malloc = caller_mallocf; new->vbr_free = caller_freef; new->vbr_closure = closure; new->vbr_timeout = DEFTIMEOUT; new->vbr_callback_int = 0; new->vbr_dns_callback = NULL; new->vbr_user_context = NULL; new->vbr_errlen = 0; new->vbr_error = NULL; new->vbr_domain = NULL; new->vbr_type = NULL; new->vbr_cert = NULL; new->vbr_trusted = NULL; new->vbr_dns_service = NULL; new->vbr_dns_start = vbr_res_query; new->vbr_dns_waitreply = vbr_res_waitreply; new->vbr_dns_cancel = vbr_res_cancel; new->vbr_dns_init = NULL; new->vbr_dns_close = NULL; new->vbr_dns_setns = NULL; new->vbr_dns_config = NULL; new->vbr_dns_trustanchor = NULL; return new; } /* ** VBR_OPTIONS -- set VBR options ** ** Parameters: ** vbr -- VBR handle to modify ** opts -- bitmask of options to use ** ** Return value: ** None. */ void vbr_options(VBR *vbr, unsigned int opts) { assert(vbr != NULL); vbr->vbr_opts = opts; } #define CLOBBER(x) if ((x) != NULL) \ { \ vbr_free(vbr, vbr->vbr_closure, (x)); \ (x) = NULL; \ } /* ** VBR_CLOSE -- shut down a VBR instance ** ** Parameters: ** vbr -- VBR handle to shut down ** ** Return value: ** None. */ void vbr_close(VBR *vbr) { assert(vbr != NULL); if (vbr->vbr_dns_close != NULL && vbr->vbr_dns_service != NULL) (void) vbr->vbr_dns_close(vbr->vbr_dns_service); CLOBBER(vbr->vbr_error); CLOBBER(vbr); } /* ** VBR_GETERROR -- return any stored error string from within the VBR ** context handle ** ** Parameters: ** vbr -- VBR handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ const u_char * vbr_geterror(VBR *vbr) { assert(vbr != NULL); return vbr->vbr_error; } /* XXX -- need a function to take in a VBR-Info: header and parse it? */ /* ** VBR_SETTIMEOUT -- set the DNS timeout ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** timeout -- requested timeout (seconds) ** ** Return value: ** A VBR_STAT_* constant. */ VBR_STAT vbr_settimeout(VBR *vbr, u_int timeout) { assert(vbr != NULL); vbr->vbr_timeout = timeout; return VBR_STAT_OK; } /* ** VBR_SETCALLBACKINT -- set the DNS callback interval ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** cbint -- requested callback interval (seconds) ** ** Return value: ** A VBR_STAT_* constant. */ VBR_STAT vbr_setcallbackint(VBR *vbr, u_int cbint) { assert(vbr != NULL); vbr->vbr_callback_int = cbint; return VBR_STAT_OK; } /* ** VBR_SETCALLBACKCTX -- set the DNS callback context ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** ctx -- context to pass to the DNS callback ** ** Return value: ** A VBR_STAT_* constant. */ VBR_STAT vbr_setcallbackctx(VBR *vbr, void *ctx) { assert(vbr != NULL); vbr->vbr_user_context = ctx; return VBR_STAT_OK; } /* ** VBR_SETDNSCALLBACK -- set the DNS wait callback ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** func -- function to call; should take an opaque context pointer ** ** Return value: ** A VBR_STAT_* constant. */ VBR_STAT vbr_setdnscallback(VBR *vbr, void (*func)(const void *context)) { assert(vbr != NULL); vbr->vbr_dns_callback = func; return VBR_STAT_OK; } /* ** VBR_SETDOMAIN -- declare the sender's domain ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** cert -- certifiers string ** ** Return value: ** None (yet). */ void vbr_setdomain(VBR *vbr, u_char *domain) { assert(vbr != NULL); assert(domain != NULL); vbr->vbr_domain = domain; } /* ** VBR_SETCERT -- store the VBR certifiers of this message ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** cert -- certifiers string ** ** Return value: ** None (yet). */ void vbr_setcert(VBR *vbr, u_char *cert) { assert(vbr != NULL); assert(cert != NULL); vbr->vbr_cert = cert; } /* ** VBR_SETTYPE -- store the VBR type of this message ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** type -- type string ** ** Return value: ** None (yet). */ void vbr_settype(VBR *vbr, u_char *type) { assert(vbr != NULL); assert(type != NULL); vbr->vbr_type = type; } /* ** VBR_TRUSTEDCERTS -- store the trusted VBR certifiers ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** certs -- NULL-terminated list of trusted certifiers ** ** Return value: ** None (yet). */ void vbr_trustedcerts(VBR *vbr, u_char **certs) { assert(vbr != NULL); assert(certs != NULL); vbr->vbr_trusted = certs; } /* ** VBR_QUERY -- query the vouching servers for results ** ** Parameters: ** vbr -- VBR handle ** res -- result string (one of "fail", "pass"); returned ** cert -- name of the certifier that returned a "pass"; returned ** ** Return value: ** VBR_STAT_OK -- able to determine a result ** VBR_STAT_INVALID -- vbr_trustedcerts(), vbr_settype() and ** vbr_setcert() were not all called ** VBR_STAT_DNSERROR -- DNS issue prevented resolution ** ** Notes: ** - "pass" is the result if ANY certifier vouched for the message. ** - "res" is not modified if no result could be determined ** - there's no attempt to validate the values found ** - vbr_cert is destroyed by this function */ VBR_STAT vbr_query(VBR *vbr, u_char **res, u_char **cert) { int c; int n; int status; int dnserr; struct vbr_query *vq; void *qh; u_char *p; u_char *last; u_char *last2; u_char *p2; struct timeval timeout; u_char certs[VBR_MAXHEADER + 1]; u_char query[VBR_MAXHOSTNAMELEN + 1]; unsigned char buf[BUFRSZ]; assert(vbr != NULL); assert(res != NULL); assert(cert != NULL); if (vbr->vbr_type == NULL || vbr->vbr_cert == NULL || vbr->vbr_trusted == NULL) { vbr_error(vbr, "required data for VBR check missing"); return VBR_STAT_INVALID; } strlcpy((char *) certs, vbr->vbr_cert, sizeof certs); if (vbr->vbr_malloc != NULL) vq = vbr->vbr_malloc(vbr->vbr_closure, sizeof(*vq)); else vq = malloc(sizeof(*vq)); if (vq == NULL) return VBR_STAT_NORESOURCE; memset(vq, '\0', sizeof *vq); for (c = 0; ; c++) { if ((vbr->vbr_opts & VBR_OPT_TRUSTEDONLY) != 0) { /* ** Query our trusted vouchers regardless of what the ** sender said. */ if (vbr->vbr_trusted[c] == NULL) break; else p = vbr->vbr_trusted[c]; } else { /* ** Query the sender's vouchers that also appear in our ** trusted voucher list. */ _Bool found; p = (u_char *) strtok_r(c == 0 ? (char *) certs : NULL, ":", (char **) &last); if (p == NULL) break; found = FALSE; for (n = 0; vbr->vbr_trusted[n] != NULL; n++) { if (strcasecmp((char *) p, (char *) vbr->vbr_trusted[n]) == 0) { found = TRUE; break; } } if (!found) continue; } snprintf((char *) query, sizeof query, "%s.%s.%s", vbr->vbr_domain, VBR_PREFIX, p); qh = NULL; if (vbr->vbr_dns_init != NULL && vbr->vbr_dns_service == NULL && vbr->vbr_dns_init(&vbr->vbr_dns_service) != 0) { snprintf(vbr->vbr_error, sizeof vbr->vbr_error, "unable to start resolver for '%s'", query); return VBR_STAT_DNSERROR; } status = vbr->vbr_dns_start(vbr->vbr_dns_service, T_TXT, query, vq->vq_buf, sizeof vq->vq_buf, &vq->vq_qh); if (status != VBR_STAT_OK) { snprintf(vbr->vbr_error, sizeof vbr->vbr_error, "unable to start query for '%s'", query); return VBR_STAT_DNSERROR; } timeout.tv_sec = vbr->vbr_timeout; timeout.tv_usec = 0; if (vbr->vbr_dns_callback == NULL) { status = vbr->vbr_dns_waitreply(vbr->vbr_dns_service, vq->vq_qh, &timeout, &vq->vq_buflen, &dnserr, NULL); } else { struct timeval *to; struct timeval wstart; struct timeval wstop; struct timeval ctimeout; wstop.tv_sec = 0; wstop.tv_usec = 0; for (;;) { (void) gettimeofday(&wstart, NULL); ctimeout.tv_sec = vbr->vbr_callback_int; ctimeout.tv_usec = 0; timeout.tv_sec = vbr->vbr_timeout; timeout.tv_usec = 0; vbr_timeouts(&timeout, &ctimeout, &wstart, &wstop, &to); status = vbr->vbr_dns_waitreply(vbr->vbr_dns_service, vq->vq_qh, to, &vq->vq_buflen, &dnserr, NULL); (void) gettimeofday(&wstop, NULL); if (status != VBR_DNS_NOREPLY || to == &timeout) break; vbr->vbr_dns_callback(vbr->vbr_user_context); } } vbr->vbr_dns_cancel(vbr->vbr_dns_service, vq->vq_qh); if (status == VBR_DNS_ERROR || status == VBR_DNS_EXPIRED) { vbr_error(vbr, "failed to retrieve %s", query); return VBR_STAT_DNSERROR; } /* try to decode the reply */ if (!vbr_txt_decode(vq->vq_buf, vq->vq_buflen, buf, sizeof buf)) continue; /* see if there's a vouch match */ for (p2 = (u_char *) strtok_r((char *) buf, " \t", (char **) &last2); p2 != NULL; p2 = (u_char *) strtok_r(NULL, " \t", (char **) &last2)) { if (strcasecmp((char *) p2, VBR_ALL) == 0 || strcasecmp((char *) p2, (char *) vbr->vbr_type) == 0) { /* we have a winner! */ *res = (u_char *) "pass"; *cert = p; return VBR_STAT_OK; } } } /* nobody vouched */ *res = (u_char *) "fail"; return VBR_STAT_OK; } /* ** VBR_GETHEADER -- generate and store the VBR-Info header ** ** Parameters: ** vbr -- VBR handle ** hdr -- header buffer ** len -- number of bytes available at "hdr" ** ** Return value: ** VBR_STAT_OK -- success ** VBR_STAT_NORESOURCE -- "hdr" was too short ** VBR_STAT_INVALID -- not all VBR information was provided */ VBR_STAT vbr_getheader(VBR *vbr, unsigned char *hdr, size_t len) { size_t olen; assert(vbr != NULL); assert(hdr != NULL); if (vbr->vbr_cert == NULL || vbr->vbr_type == NULL) { vbr_error(vbr, "VBR certifiers or type missing"); return VBR_STAT_INVALID; } olen = snprintf((char *) hdr, len, "md=%s; mc=%s; mv=%s", vbr->vbr_domain, vbr->vbr_type, vbr->vbr_cert); if (olen >= len) { vbr_error(vbr, "VBR buffer too small"); return VBR_STAT_NORESOURCE; } return VBR_STAT_OK; } /* ** VBR_DNS_SET_QUERY_SERVICE -- stores a handle representing the DNS ** query service to be used, returning any ** previous handle ** ** Parameters: ** vbr -- VBR library handle ** h -- handle to be used ** ** Return value: ** Previously stored handle, or NULL if none. */ void * vbr_dns_set_query_service(VBR *vbr, void *h) { void *old; assert(vbr != NULL); old = vbr->vbr_dns_service; vbr->vbr_dns_service = h; return old; } /* ** VBR_DNS_SET_QUERY_START -- stores a pointer to a query start function ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to start queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- receives handle stored by ** vbr_dns_set_query_service() ** int type -- DNS RR query type (C_IN assumed) ** char *query -- question to ask ** char *buf -- buffer into which to write reply ** size_t buflen -- size of buf ** void **qh -- returned query handle */ void vbr_dns_set_query_start(VBR *vbr, int (*func)(void *, int, unsigned char *, unsigned char *, size_t, void **)) { assert(vbr != NULL); vbr->vbr_dns_start = func; } /* ** VBR_DNS_SET_QUERY_CANCEL -- stores a pointer to a query cancel function ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to cancel running queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- query handle to be canceled */ void vbr_dns_set_query_cancel(VBR *vbr, int (*func)(void *, void *)) { assert(vbr != NULL); vbr->vbr_dns_cancel = func; } /* ** VBR_DNS_SET_QUERY_WAITREPLY -- stores a pointer to wait for a DNS reply ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to wait for a reply ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- handle of query that has completed ** struct timeval *timeout -- how long to wait ** size_t *bytes -- bytes returned ** int *error -- error code returned ** int *dnssec -- DNSSEC status returned */ void vbr_dns_set_query_waitreply(VBR *vbr, int (*func)(void *, void *, struct timeval *, size_t *, int *, int *)) { assert(vbr != NULL); vbr->vbr_dns_waitreply = func; } /* ** VBR_DNS_SET_INIT -- stores a pointer to a function that initializes ** a resolver ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to initialize a resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void **dns -- DNS service handle (returned) */ void vbr_dns_set_init(VBR *vbr, int (*func)(void **)) { assert(vbr != NULL); vbr->vbr_dns_init = func; } /* ** VBR_DNS_SET_CLOSE -- stores a pointer to a function that terminates ** a resolver ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to terminate a resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns void ** void *dns -- DNS service handle */ void vbr_dns_set_close(VBR *vbr, void (*func)(void *)) { assert(vbr != NULL); vbr->vbr_dns_close = func; } /* ** VBR_DNS_SET_NSLIST -- stores a pointer to a function that updates ** the active nameserver list ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to update the active nameserver list ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** const char *nslist -- nameserver list */ void vbr_dns_set_nslist(VBR *vbr, int (*func)(void *, const char *)) { assert(vbr != NULL); vbr->vbr_dns_setns = func; } /* ** VBR_DNS_SET_CONFIG -- stores a pointer to a function that provides ** resolver configuration ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to pass resolver configuration data ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** const char *config -- resolver configuration data */ void vbr_dns_set_config(VBR *vbr, int (*func)(void *, const char *)) { assert(vbr != NULL); vbr->vbr_dns_config = func; } /* ** VBR_DNS_SET_TRUSTANCHOR -- stores a pointer to a function that provides ** trust anchor data ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to pass trust anchor data ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** const char *trust -- trust anchor data */ void vbr_dns_set_trustanchor(VBR *vbr, int (*func)(void *, const char *)) { assert(vbr != NULL); vbr->vbr_dns_trustanchor = func; } /* ** VBR_DNS_NSLIST -- requests update to a nameserver list ** ** Parameters: ** lib -- RBL library handle ** nslist -- comma-separated list of nameservers to use ** ** Return value: ** An VBR_STAT_* constant. */ VBR_STAT vbr_dns_nslist(VBR *lib, const char *nslist) { int status; assert(lib != NULL); assert(nslist != NULL); if (lib->vbr_dns_setns != NULL) { status = lib->vbr_dns_setns(lib->vbr_dns_service, nslist); if (status != 0) return VBR_STAT_DNSERROR; } return VBR_STAT_OK; } /* ** VBR_DNS_CONFIG -- requests a change to resolver configuration ** ** Parameters: ** lib -- RBL library handle ** config -- opaque configuration string ** ** Return value: ** An VBR_STAT_* constant. */ VBR_STAT vbr_dns_config(VBR *lib, const char *config) { int status; assert(lib != NULL); assert(config != NULL); if (lib->vbr_dns_config != NULL) { status = lib->vbr_dns_config(lib->vbr_dns_service, config); if (status != 0) return VBR_STAT_DNSERROR; } return VBR_STAT_OK; } /* ** VBR_DNS_TRUSTANCHOR -- requests a change to resolver trust anchor data ** ** Parameters: ** lib -- RBL library handle ** trust -- opaque trust anchor string ** ** Return value: ** An VBR_STAT_* constant. */ VBR_STAT vbr_dns_trustanchor(VBR *lib, const char *trust) { int status; assert(lib != NULL); assert(trust != NULL); if (lib->vbr_dns_trustanchor != NULL) { status = lib->vbr_dns_trustanchor(lib->vbr_dns_service, trust); if (status != 0) return VBR_STAT_DNSERROR; } return VBR_STAT_OK; } /* ** VBR_DNS_INIT -- force nameserver (re)initialization ** ** Parameters: ** lib -- RBL library handle ** ** Return value: ** An VBR_STAT_* constant. */ VBR_STAT vbr_dns_init(VBR *lib) { int status; assert(lib != NULL); if (lib->vbr_dns_service != NULL && lib->vbr_dns_close != NULL) lib->vbr_dns_close(lib->vbr_dns_service); lib->vbr_dns_service = NULL; if (lib->vbr_dns_init != NULL) return lib->vbr_dns_init(&lib->vbr_dns_service); else return VBR_STAT_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/vbr.h000066400000000000000000000267041337314105200207100ustar00rootroot00000000000000/* ** Copyright (c) 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. ** All rights reserved. */ #ifndef _VBR_H_ #define _VBR_H_ /* system includes */ #include /* strings */ #define VBR_ALL "all" #define VBR_INFOHEADER "VBR-Info" #define VBR_PREFIX "_vouch" /* definitions */ #define VBR_MAXHEADER 1024 #define VBR_MAXHOSTNAMELEN 256 /* return codes */ typedef int VBR_STAT; #define VBR_STAT_OK 0 #define VBR_STAT_INVALID 1 #define VBR_STAT_DNSERROR 2 #define VBR_STAT_NORESOURCE 3 #define VBR_STAT_NOTIMPLEMENT 4 #define VBR_OPT_TRUSTEDONLY 0x01 /* types */ struct vbr_handle; typedef struct vbr_handle VBR; /* prototypes */ /* ** VBR_INIT -- initialize a VBR handle ** ** Parameters: ** caller_mallocf -- caller-provided memory allocation function ** caller_freef -- caller-provided memory release function ** closure -- memory closure to pass to the above when used ** ** Return value: ** A new VBR handle suitable for use with other VBR functions, or ** NULL on failure. ** ** Side effects: ** Strange radar returns at Indianapolis ARTCC. */ extern VBR * vbr_init __P((void *(*caller_mallocf)(void *closure, size_t nbytes), void (*caller_freef)(void *closure, void *p), void *closure)); /* ** VBR_OPTIONS -- set VBR options ** ** Parameters: ** vbr -- VBR handle to modify ** opts -- bitmask of options to use ** ** Return value: ** None. */ extern void vbr_options __P((VBR *, unsigned int)); /* ** VBR_CLOSE -- shut down a VBR instance ** ** Parameters: ** vbr -- VBR handle to shut down ** ** Return value: ** None. */ extern void vbr_close __P((VBR *)); /* ** VBR_GETERROR -- return any stored error string from within the VBR ** context handle ** ** Parameters: ** vbr -- VBR handle from which to retrieve an error string ** ** Return value: ** A pointer to the stored string, or NULL if none was stored. */ extern const u_char *vbr_geterror __P((VBR *)); /* ** VBR_GETHEADER -- generate and store the VBR-Info header ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** hdr -- header buffer ** len -- number of bytes available at "hdr" ** ** Return value: ** STAT_OK -- success ** STAT_NORESOURCE -- "hdr" was too short */ extern VBR_STAT vbr_getheader __P((VBR *, unsigned char *, size_t)); /* ** VBR_SETCERT -- store the VBR certifiers of this message ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** cert -- certifiers string ** ** Return value: ** None (yet). */ extern void vbr_setcert __P((VBR *, u_char *)); /* ** VBR_SETTYPE -- store the VBR type of this message ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** type -- type string ** ** Return value: ** None (yet). */ extern void vbr_settype __P((VBR *, u_char *)); /* ** VBR_SETDOMAIN -- declare the sender's domain ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** cert -- certifiers string ** ** Return value: ** None (yet). */ extern void vbr_setdomain __P((VBR *, u_char *)); /* ** VBR_TRUSTEDCERTS -- set list of trusted certifiers ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** certs -- NULL terminted vector of trusted certifier names ** ** Return value: ** None (yet). */ extern void vbr_trustedcerts __P((VBR *, u_char **)); /* ** VBR_QUERY -- query the vouching servers for results ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** res -- result string (one of "fail", "pass"); returned ** cert -- name of the certifier that returned a "pass"; returned ** ** Return value: ** VBR_STAT_OK -- able to determine a result ** VBR_STAT_INVALID -- vbr_trustedcerts(), vbr_settype() and ** vbr_setcert() were not all called ** VBR_STAT_CANTVRFY -- DNS issue prevented resolution ** ** Notes: ** - "pass" is the result if ANY certifier vouched for the message. ** - "res" is not modified if no result could be determined ** - "cert" and "domain" are not modified if a "pass" is not returned ** - there's no attempt to validate the values found */ extern VBR_STAT vbr_query __P((VBR *, u_char **, u_char **)); /* ** VBR_SETTIMEOUT -- set the DNS timeout ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** timeout -- requested timeout (seconds) ** ** Return value: ** A VBR_STAT_* constant. */ extern VBR_STAT vbr_settimeout __P((VBR *, u_int)); /* ** VBR_SETCALLBACKINT -- set the DNS callback interval ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** cbint -- requested callback interval (seconds) ** ** Return value: ** A VBR_STAT_* constant. */ extern VBR_STAT vbr_setcallbackint __P((VBR *, u_int)); /* ** VBR_SETCALLBACKCTX -- set the DNS callback context ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** ctx -- context to pass to the DNS callback ** ** Return value: ** A VBR_STAT_* constant. */ extern VBR_STAT vbr_setcallbackctx __P((VBR *, void *)); /* ** VBR_SETDNSCALLBACK -- set the DNS wait callback ** ** Parameters: ** vbr -- VBR handle, created by vbr_init() ** func -- function to call; should take an opaque context pointer ** ** Return value: ** A VBR_STAT_* constant. */ extern VBR_STAT vbr_setdnscallback __P((VBR *vbr, void (*func)(const void *context))); /* ** VBR_DNS_SET_QUERY_SERVICE -- stores a handle representing the DNS ** query service to be used, returning any ** previous handle ** ** Parameters: ** vbr -- VBR library handle ** h -- handle to be used ** ** Return value: ** Previously stored handle, or NULL if none. */ extern void *vbr_dns_set_query_service __P((VBR *, void *)); /* ** VBR_DNS_SET_QUERY_START -- stores a pointer to a query start function ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to start queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- receives handle stored by ** vbr_dns_set_query_service() ** int type -- DNS RR query type (C_IN assumed) ** char *query -- question to ask ** char *buf -- buffer into which to write reply ** size_t buflen -- size of buf ** void **qh -- returned query handle */ extern void vbr_dns_set_query_start __P((VBR *, int (*)(void *, int, unsigned char *, unsigned char *, size_t, void **))); /* ** VBR_DNS_SET_QUERY_CANCEL -- stores a pointer to a query cancel function ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to cancel running queries ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- query handle to be canceled */ extern void vbr_dns_set_query_cancel __P((VBR *, int (*)(void *, void *))); /* ** VBR_DNS_SET_QUERY_WAITREPLY -- stores a pointer to wait for a DNS reply ** ** Parameters: ** vbr -- VBR library handle ** func -- function to use to wait for a reply ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *dns -- DNS service handle ** void *qh -- handle of query that has completed ** struct timeval *timeout -- how long to wait ** size_t *bytes -- bytes returned ** int *error -- error code returned ** int *dnssec -- DNSSEC status returned */ extern void vbr_dns_set_query_waitreply __P((VBR *, int (*)(void *, void *, struct timeval *, size_t *, int *, int *))); /* ** VBR_DNS_SET_NSLIST -- set function that updates resolver nameserver list ** ** Parameters: ** lib -- VBR library handle ** func -- function to use to update the nameserver list ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int ** void *srv -- DNS service handle ** const char *nslist -- nameserver list, as a comma-separated ** string */ extern void vbr_dns_set_nslist __P((VBR *, int (*)(void *, const char *))); /* ** VBR_DNS_SET_CLOSE -- shuts down the resolver ** ** Parameters: ** lib -- VBR library handle ** func -- function to use to shut down the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns void ** void *srv -- DNS service handle */ extern void vbr_dns_set_close __P((VBR *, void (*)(void *))); /* ** VBR_DNS_SET_INIT -- initializes the resolver ** ** Parameters: ** lib -- VBR library handle ** func -- function to use to initialize the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void **srv -- DNS service handle (updated) */ extern void vbr_dns_set_init __P((VBR *, int (*)(void **))); /* ** VBR_DNS_SET_CONFIG -- configures the resolver ** ** Parameters: ** lib -- VBR library handle ** func -- function to use to configure the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *srv -- DNS service handle ** const char *config -- arbitrary resolver configuration data */ extern void vbr_dns_set_config __P((VBR *, int (*)(void *, const char *))); /* ** VBR_DNS_SET_TRUSTANCHOR -- provides trust anchor data to the resolver ** ** Parameters: ** lib -- VBR library handle ** func -- function to use to pass trust anchor data to the resolver ** ** Return value: ** None. ** ** Notes: ** "func" should match the following prototype: ** returns int (status) ** void *srv -- DNS service handle ** const char *trust -- arbitrary trust anchor data */ extern void vbr_dns_set_trustanchor __P((VBR *, int (*)(void *, const char *))); /* ** VBR_DNS_NSLIST -- requests update to a nameserver list ** ** Parameters: ** lib -- VBR library handle ** nslist -- comma-separated list of nameservers to use ** ** Return value: ** An VBR_STAT_* constant. */ extern VBR_STAT vbr_dns_nslist __P((VBR *, const char *)); /* ** VBR_DNS_CONFIG -- requests a change to resolver configuration ** ** Parameters: ** lib -- VBR library handle ** config -- opaque configuration string ** ** Return value: ** An VBR_STAT_* constant. */ extern VBR_STAT vbr_dns_config __P((VBR *, const char *)); /* ** VBR_DNS_TRUSTANCHOR -- requests a change to resolver trust anchor data ** ** Parameters: ** lib -- VBR library handle ** trust -- opaque trust anchor string ** ** Return value: ** An VBR_STAT_* constant. */ extern VBR_STAT vbr_dns_trustanchor __P((VBR *, const char *)); /* ** VBR_DNS_INIT -- force nameserver (re)initialization ** ** Parameters: ** lib -- VBR library handle ** ** Return value: ** An VBR_STAT_* constant. */ extern VBR_STAT vbr_dns_init __P((VBR *)); #endif /* _VBR_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/libvbr/vbr.pc.in000066400000000000000000000005741337314105200214650ustar00rootroot00000000000000# Process this file with autoconf to produce a pkg-config metadata file. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: VBR (Vouch by reference library) Description: Library for assisting in Vouch By Refence functions URL: http://opendkim.org Version: @VERSION@ Libs: -L${libdir} -lvbr Libs.private: @LIBRESOLV@ Cflags: -I${includedir} OpenDKIM-rel-opendkim-2-11-0-Beta2/m4/000077500000000000000000000000001337314105200167755ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/m4/.gitignore000066400000000000000000000000771337314105200207710ustar00rootroot00000000000000libtool.m4 ltoptions.m4 ltsugar.m4 ltversion.m4 lt~obsolete.m4 OpenDKIM-rel-opendkim-2-11-0-Beta2/m4/ac_pthread.m4000066400000000000000000000326761337314105200213470ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # 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 3 of the License, or (at your # option) any later version. # # 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. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 21 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case ${host_os} in solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac # Clang doesn't consider unrecognized options an error unless we specify # -Werror. We throw in some extra Clang-specific options to ensure that # this doesn't happen for GCC, which also accepts -Werror. AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) save_CFLAGS="$CFLAGS" ax_pthread_extra_flags="-Werror" CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], [AC_MSG_RESULT([yes])], [ax_pthread_extra_flags= AC_MSG_RESULT([no])]) CFLAGS="$save_CFLAGS" if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT([$ax_pthread_ok]) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $attr; return attr /* ; */])], [attr_name=$attr; break], []) done AC_MSG_RESULT([$attr_name]) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case ${host_os} in aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; osf* | hpux*) flag="-D_REENTRANT";; solaris*) if test "$GCC" = "yes"; then flag="-D_REENTRANT" else # TODO: What about Clang on Solaris? flag="-mt -D_REENTRANT" fi ;; esac AC_MSG_RESULT([$flag]) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], [ax_cv_PTHREAD_PRIO_INHERIT], [ AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: compile with *_r variant if test "x$GCC" != xyes; then case $host_os in aix*) AS_CASE(["x/$CC"], [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], [#handle absolute path differently from PATH based program lookup AS_CASE(["x$CC"], [x/*], [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD OpenDKIM-rel-opendkim-2-11-0-Beta2/miltertest/000077500000000000000000000000001337314105200206515ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/miltertest/.gitignore000066400000000000000000000007361337314105200226470ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure configure.scan aclocal.m4 depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile .deps opendkim-testadsp opendkim opendkim-stats opendkim-testkey .libs core *.core opendkim*.[58] miltertest OpenDKIM-rel-opendkim-2-11-0-Beta2/miltertest/Makefile.am000066400000000000000000000011501337314105200227020ustar00rootroot00000000000000# Copyright (c) 2010, 2012, 2013, The Trusted Domain Project. # All rights reserved. # what flags you want to pass to the C compiler & linker #AM_CFLAGS = --pedantic -Wall -O2 # this lists the binaries to produce, the (non-PHONY, binary) targets in # the previous manual Makefile if LUA bin_PROGRAMS = miltertest miltertest_SOURCES = miltertest.c miltertest_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBMILTER_INCDIRS) $(LIBLUA_INCDIRS) miltertest_LDFLAGS = ../libopendkim/libopendkim.la $(LIBLUA_LIBDIRS) miltertest_LDADD = $(LIBLUA_LIBS) $(LIBNSL_LIBS) man_MANS = miltertest.8 endif EXTRA_DIST = miltertest.8 OpenDKIM-rel-opendkim-2-11-0-Beta2/miltertest/miltertest.8000066400000000000000000000375331337314105200231510ustar00rootroot00000000000000.TH miltertest 8 "The Trusted Domain Project" .SH NAME .B miltertest \- milter unit test utility .SH SYNOPSIS .B miltertest [\-D name[=value]] [\-s script] [\-u] [\-v] [\-V] [\-w] .SH DESCRIPTION .B miltertest simulates the MTA side of an MTA-milter interaction for testing a milter-aware filter application. It takes as input a script using the Lua language, and by exporting some utility functions, makes it possible for users to write scripts that exercise a filter. See documentation on Lua (e.g. http://www.lua.org) for the syntax of the language in general. The documentation below describes functions that are added to Lua by this application to make testing possible. Documentation on milter can be found at http://www.milter.org. A particular transaction must follow a series of steps to be completed, namely negotiate, connection information, envelope sender, envelope recipient(s), header field(s), end-of-header, body chunk(s), end-of-message. To make the work of writing tests with .B miltertest simpler, any of these steps prior to end-of-message that is skipped will be filled in using arbitrary, but legal, data. Interspersed with these protocol phases are optional macro (key/value) deliveries from the MTA. .B miltertest will never send these automatically. If they are needed for your tests, you must send them as part of your test script. .SH OPTIONS .TP .I -D name[=value] Defines a global variable called .I name to the Lua interpreter. If a .I value is provided, the global variable is set to that value (as a string, although Lua can convert strings to numbers internally). If no .I value is provided, the global variable is set to 1. .TP .I -s script Use the contents of file .I script as the Lua script to be executed. The default is to read from standard input. .TP .I -u After the filter being tested is terminated, report user and system time consumed. See .I getrusage(2). .TP .I -v Increase verbose output. May be specified multiple times to request more and more information. .TP .I -V Print version number and exit. .TP .I -w Don't wait for child status to be returned when testing is complete. .SH FUNCTIONS The following functions are made available to Lua scripts for exercising a filter. All functions return Lua constant "nil" on success or an error string on failure, unless otherwise indicated. .TP .B mt.abort(conn) Aborts the transaction in progress on the specified connection. .TP .B mt.bodyfile(conn, file) Sends the contents of the named .I file to the connection as body data. If there is any error opening .I file for reading, the test aborts. .TP .B mt.bodyrandom(conn, n) Sends at least .I n bytes of random-length lines of random printable ASCII data as body chunks to the specified connection. .TP .B mt.bodystring(conn, str) Sends .I str as a chunk of body text on the specified connection. .TP .B mt.chdir(directory) Changes the current working directory to the named .I directory. .TP .B mt.connect(sockinfo[, count, interval]) Makes a connection to a filter listening at the socket described by .I sockinfo. Returns a handle referring to that connection, or the Lua constant "nil" on error. If .I count and .I interval are included, they specify the number of times to try to connect to the filter and the delay between each connection in seconds (with floating point values permitted). If the environment variable MILTERTEST_RETRY_SPEED_FACTOR is set and appears to contain an integer, the value of .I interval (if set) will be multiplied by the value found in that environment variable. This is included to allow tests in a large test suite to be easily adjusted on slow systems without reconfiguring the entire test suite. .TP .B mt.conninfo(conn, host, ip) Sends information about a new SMTP connection to the MTA, represented by connection .I conn, from the host named .I host at IP address .I ip (both strings). If .I host is the Lua constant "nil", the string "localhost" is assumed. If .I ip is the Lua constant "nil", a DNS query will be made for the IP address matching .I host; if none is found, the test will abort. The .I ip may also be the special string "unspec", which will tell the filter that a connection came in from an unknown protocol family. .TP .B mt.data(conn) Announces the DATA command on the specified connection, which occurs between the last RCPT TO command and the beginning of the header block. .TP .B mt.disconnect(conn[, polite])) Sends a "quit" message to the specified connection and then closes that connection. The specified .I conn handle should no longer be used. If .I polite is defined, it must be a Boolean indicating whether a normal disconnect should be done (true) or an abrupt disconnect should be done (false). An abrupt disconnect skips standard protocol shutdown steps. .TP .B mt.echo(string) Prints the specified .I string on standard output. Returns nothing. .TP .B mt.eoh(conn) Announces end-of-header on the specified connection. .TP .B mt.eom(conn) Announces end-of-message on the specified connection, and begins capturing any other operations the filter might perform in that phase. .TP .B mt.eom_check(conn, op, param[, ...]) Checks the captured set of EOM operations (see above) to determine whether or not specific milter actions were requested by the filter. Returns a Boolean value (true or false). See the EOM CHECKS section for details. .TP .B mt.getheader(conn, hdr, n) Retrieves the value of the .I nth instance of header field named .I hdr added during end-of-message processing on the specified connection. This can be used by the script to verify that the header thus added contains the right thing. Returns the value as a string, or the Lua constant "nil" on error. .TP .B mt.getcwd() Returns the current working directory as a string. .TP .B mt.getreply(conn) Returns the last milter reply received from the specified connection, as an integer. This can be compared to any of the SMFIR_* constants defined by milter to see if the filter responded as expected. This value is initially set to the NULL character. .TP .B mt.header(conn, name, value) Sends the header with the given .I name and .I value to the specified connection. .TP .B mt.helo(conn, name) Sends HELO/EHLO information using the specified .I name as the parameter given. .TP .B mt.macro(conn, type, name, value[, name2, value2[, ...]]) Declares a macro called .I name whose value is .I value and whose type (matching protocol element) is .I type. Valid types are SMFIC_CONNECT, SMFIC_HELO, SMFIC_MAIL and SMFIC_RCPT. Multiple macro names and values can be provided, but they must appear in pairs. .TP .B mt.mailfrom(conn, envfrom[, ...]) Announces .I envfrom as the envelope sender of a new message. ESMTP parameters as additional arguments are permitted. .TP .B mt.negotiate(conn, version, actions, steps) Performs milter option negotiation with the connection .I conn, advertising that the specified protocol .I version, protocol .I actions and protocol .I steps are offered by the MTA. Returns the Lua constant "nil" on success or an error string on failure. If any of the protocol parameters are "nil", the current defaults (defined in .I libmilter/mfdef.h, provided with the milter source code) will be used. .TP .B mt.rcptto(conn, envrcpt[, ...]) Announces .I envrcpt as an envelope recipient of a message. ESMTP parameters as additional arguments are permitted. .TP .B mt.set_timeout(n) Sets the read timeout to .I n seconds. The default is ten seconds. Returns nothing. .TP .B mt.sleep(n) Sleeps for .I n seconds. The value may be an integer (for whole seconds) or a floating-point value (for partial seconds). .TP .B mt.signal(n) Sends the specified signal number .I n to the running filter. .TP .B mt.startfilter(path, arg1, arg2, ...) Starts the filter whose binary is located at .I path with argument vector comprised of strings .I path, .I arg1, .I arg2, etc. Basically this is almost the same syntax as .I execl(3) except that .B miltertest also does the fork for you, and will remember the process ID in order to request a clean shutdown using SIGTERM and .I wait(2) at the end of the test script. If the filter could not be started, an exception is generated with an error message returned. .TP .B mt.test_action(conn, action) Tests whether or not the connection represented by .I conn requested the specified milter protocol .I action, specified by an SMFIF_* constant, during option negotiation. (See the libmilter documentation and/or include files for details.) .TP .B mt.test_option(conn, option) Tests whether or not the connection represented by .I conn requested the specified milter protocol .I option, specified by an SMFIP_* constant, during option negotiation. (See the libmilter documentation and/or include files for details.) .TP .B mt.unknown(conn, str) Announces that the unknown SMTP command .I str arrived over the connection represented by .I conn. .SH EOM CHECKS The .B mt.eom_check() function is used to determine what changes to the message the filter requested during its EOM callback. The changes can be requested in any order. The first parameter, .I op, indicates what operation is of interest, and it also dictates what the possible parameter list is. Valid values and corresponding parameters for .I op are as follows: .TP .I MT_HDRADD Checks to see if a header field was added to the message. If no parameters are given, the function returns true if any header field was added. If one parameter was given, the function returns true only if the named header field was added (regardless of its value). If two parameters are given, the function returns true only if the named header field was added with the specified value. .TP .I MT_HDRCHANGE Checks to see if an existing header field was changed. If no parameters are given, the function returns true if any header field was modified. If one parameter was given, the function returns true only if the named header field was modified (regardless of its new value). If two parameters are given, the function returns true only if the named header field was modified to have the specified new value. .TP .I MT_HDRDELETE Checks to see if an existing header field was deleted. If no parameters are given, the function returns true if any header field was deleted. If one parameter was given, the function returns true only if the named header field was deleted. .TP .I MT_HDRINSERT Checks to see if a header field was inserted into the message. If no parameters are given, the function returns true if any header field was added. If one parameter was given, the function returns true only if the named header field was added (regardless of its value). If two parameters are given, the function returns true only if the named header field was added with the specified value. If three parameters are given, the function returns true only if the named header field was added with the specified value at the specified index. .TP .I MT_RCPTADD Checks to see if an envelope recipient was added. Currently only one parameter may be provided. .TP .I MT_RCPTDELETE Checks to see if an envelope recipient was deleted. Currently only one parameter may be provided. .TP .I MT_BODYCHANGE Checks to see if the message's body was replaced by other content. With no parameters, the function returns true only if the body was changed (regardless of the new content). With one parameter, the function returns true only if the body was changed to the specified new content. .TP .I MT_QUARANTINE Checks to see if the filter requested quarantining of the message. With no parameters, the function returns true only if quarantine was requested. With one parameter, the function returns true only if quarantine was requested with the specified reason string. .TP .I MT_SMTPREPLY Checks to see if the filter requested a specific SMTP reply message. With no parameters, the function returns true only if a specific reply was requested. With one parameter, the function returns true only if a specific reply was requested with the specified SMTP code. With two parameters, the function returns true only if a specific reply was requested with the specified SMTP code and enhanced status code. With three parameters, the function returns true only if a specific reply was requested with the specified SMTP code, enhanced status code, and text. .SH EXAMPLE .PD 0 -- Echo that the test is starting .PP mt.echo("*** begin test") .PP -- start the filter .PP mt.startfilter("../myfilter", "\-p", "inet:12345@localhost") .PP mt.sleep(2) .PP -- try to connect to it .PP conn = mt.connect("inet:12345@localhost") .PP if conn == nil then .PP error "mt.connect() failed" .PP end .PP -- send connection information .PP -- mt.negotiate() is called implicitly .PP if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then .PP error "mt.conninfo() failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.conninfo() unexpected reply" .PP end .PP -- send envelope macros and sender data .PP -- mt.helo() is called implicitly .PP mt.macro(conn, SMFIC_MAIL, "i", "test-id") .PP if mt.mailfrom(conn, "user@example.com") ~= nil then .PP error "mt.mailfrom() failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.mailfrom() unexpected reply" .PP end -- send headers .PP -- mt.rcptto() is called implicitly .PP if mt.header(conn, "From", "user@example.com") ~= nil then .PP error "mt.header(From) failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.header(From) unexpected reply" .PP end .PP if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 \-0800") ~= nil then .PP error "mt.header(Date) failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.header(Date) unexpected reply" .PP end .PP if mt.header(conn, "Subject", "Signing test") ~= nil then .PP error "mt.header(Subject) failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.header(Subject) unexpected reply" .PP end .PP -- send EOH .PP if mt.eoh(conn) ~= nil then .PP error "mt.eoh() failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.eoh() unexpected reply" .PP end .PP -- send body .PP if mt.bodystring(conn, "This is a test!\\r\\n") ~= nil then .PP error "mt.bodystring() failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_CONTINUE then .PP error "mt.bodystring() unexpected reply" .PP end .PP .PP -- end of message; let the filter react .PP if mt.eom(conn) ~= nil then .PP error "mt.eom() failed" .PP end .PP if mt.getreply(conn) ~= SMFIR_ACCEPT then .PP error "mt.eom() unexpected reply" .PP end -- verify that a test header field got added .PP if not mt.eom_check(conn, MT_HDRINSERT, "Test-Header") then .PP error "no header added" .PP end -- wrap it up! .PP mt.disconnect(conn) .PD .SH NOTES If a filter negotiates one of the SMFIP_NO* protocol option bits and a script attempts to perform one of those protocol steps, an error is returned. It is up to the test author to use .I mt.test_option() function to see if performing a protocol step has been explicitly disabled by the filter. .SH MILTER NOTES When .I mt.macro() is called, it replaces all previous macros of the same .I type with the ones provided in the argument list. Thus, one call should be made that lists the complete set rather than one call per name-value pair. Also, as each stage in the milter process is executed, all macros corresponding stages after the current one are discarded. For example, calling .I mt.helo(), which corresponds to SMFIC_HELO, will cause all prior macros of type SMFIC_MAIL and SMFIC_RCPT to be discarded as they represent a milter stage that comes later than SMFIC_HELO. Since the milter protocol and the internals of libmilter itself are not formally documented, there are myriad other subtleties of the milter protocol and implementation that are not documented here and may not be documented elsewhere, and could change without notice. Caveat emptor. .SH VERSION This man page covers version 1.5.0 of .I miltertest. .SH COPYRIGHT Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved. .SH SEE ALSO Milter -- http://www.milter.org .P Lua -- http://www.lua.org OpenDKIM-rel-opendkim-2-11-0-Beta2/miltertest/miltertest.c000066400000000000000000002351451337314105200232230ustar00rootroot00000000000000/* ** Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* libmilter includes */ #include #ifndef SMFI_PROT_VERSION # define SMFI_PROT_VERSION SMFI_VERSION #endif /* ! SMFI_PROT_VERSION */ /* libopendkim includes */ #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* Lua includes */ #include #include #include /* types */ #ifndef HAVE_USECONDS_T typedef unsigned int useconds_t; #endif /* ! HAVE_USECONDS_T */ /* macros */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifdef SMFIP_NODATA # define CHECK_MPOPTS(c,o) (((c)->ctx_mpopts & (o)) != 0) #else /* SMFIP_NODATA */ # define CHECK_MPOPTS(c,o) 0 #endif /* SMFIP_NODATA */ #ifndef SMFIP_NR_CONN # define SMFIP_NR_CONN 0 # define SMFIP_NR_HELO 0 # define SMFIP_NR_MAIL 0 # define SMFIP_NR_RCPT 0 # define SMFIP_NR_DATA 0 # define SMFIP_NR_HDR 0 # define SMFIP_NR_EOH 0 # define SMFIP_NR_BODY 0 # define SMFIP_NR_UNKN 0 #endif /* SMFIP_NR_CONN */ #define MT_PRODUCT "OpenDKIM milter test facility" #define MT_VERSION "1.6.0" #define BUFRSZ 1024 #define CHUNKSZ 65536 #define CMDLINEOPTS "D:s:uvVw" #define DEFBODY "Dummy message body.\r\n" #define DEFCLIENTPORT 12345 #define DEFCLIENTHOST "test.example.com" #define DEFCLIENTIP "12.34.56.78" #define DEFHEADERNAME "From" #define DEFSENDER "" #define DEFTIMEOUT 10 #define DEFRECIPIENT "" #define STATE_UNKNOWN (-1) #define STATE_INIT 0 #define STATE_NEGOTIATED 1 #define STATE_CONNINFO 2 #define STATE_HELO 3 #define STATE_ENVFROM 4 #define STATE_ENVRCPT 5 #define STATE_DATA 6 #define STATE_HEADER 7 #define STATE_EOH 8 #define STATE_BODY 9 #define STATE_EOM 10 #define STATE_DEAD 99 #define MT_HDRADD 1 #define MT_HDRINSERT 2 #define MT_HDRCHANGE 3 #define MT_HDRDELETE 4 #define MT_RCPTADD 5 #define MT_RCPTDELETE 6 #define MT_BODYCHANGE 7 #define MT_QUARANTINE 8 #define MT_SMTPREPLY 9 /* prototypes */ int mt_abort(lua_State *); int mt_bodyfile(lua_State *); int mt_bodyrandom(lua_State *); int mt_bodystring(lua_State *); int mt_chdir(lua_State *); int mt_connect(lua_State *); int mt_conninfo(lua_State *); int mt_data(lua_State *); int mt_disconnect(lua_State *); int mt_echo(lua_State *); int mt_eoh(lua_State *); int mt_eom(lua_State *); int mt_eom_check(lua_State *); int mt_getcwd(lua_State *); int mt_getheader(lua_State *); int mt_getreply(lua_State *); int mt_header(lua_State *); int mt_helo(lua_State *); int mt_macro(lua_State *); int mt_mailfrom(lua_State *); int mt_negotiate(lua_State *); int mt_rcptto(lua_State *); int mt_set_timeout(lua_State *); int mt_signal(lua_State *); int mt_sleep(lua_State *); int mt_startfilter(lua_State *); int mt_test_action(lua_State *); int mt_test_option(lua_State *); int mt_unknown(lua_State *); /* data types */ struct mt_eom_request { char eom_request; /* request code */ size_t eom_rlen; /* request length */ char * eom_rdata; /* request data */ struct mt_eom_request * eom_next; /* next request */ }; struct mt_context { char ctx_response; /* milter response code */ int ctx_fd; /* descriptor */ int ctx_state; /* current state */ unsigned long ctx_mactions; /* requested actions */ unsigned long ctx_mpopts; /* requested protocol opts */ struct mt_eom_request * ctx_eomreqs; /* EOM requests */ }; struct mt_lua_io { _Bool lua_io_done; size_t lua_io_scriptlen; const char * lua_io_script; }; static const luaL_Reg mt_library[] = { { "abort", mt_abort }, { "bodyfile", mt_bodyfile }, { "bodyrandom", mt_bodyrandom }, { "bodystring", mt_bodystring }, { "chdir", mt_chdir }, { "connect", mt_connect }, { "conninfo", mt_conninfo }, { "data", mt_data }, { "disconnect", mt_disconnect }, { "echo", mt_echo }, { "eoh", mt_eoh }, { "eom", mt_eom }, { "eom_check", mt_eom_check }, { "getcwd", mt_getcwd }, { "getheader", mt_getheader }, { "getreply", mt_getreply }, { "header", mt_header }, { "helo", mt_helo }, { "macro", mt_macro }, { "mailfrom", mt_mailfrom }, { "negotiate", mt_negotiate }, { "rcptto", mt_rcptto }, { "set_timeout", mt_set_timeout }, { "signal", mt_signal }, { "sleep", mt_sleep }, { "startfilter", mt_startfilter }, { "test_action", mt_test_action }, { "test_option", mt_test_option }, { "unknown", mt_unknown }, { NULL, NULL } }; /* globals */ _Bool rusage; _Bool nowait; int verbose; unsigned int tmo; pid_t filterpid; char scriptbuf[BUFRSZ]; char *progname; /* ** MT_INET_NTOA -- thread-safe inet_ntoa() ** ** Parameters: ** a -- (struct in_addr) to be converted ** buf -- destination buffer ** buflen -- number of bytes at buf ** ** Return value: ** Size of the resultant string. If the result is greater than buflen, ** then buf does not contain the complete result. */ size_t mt_inet_ntoa(struct in_addr a, char *buf, size_t buflen) { in_addr_t addr; assert(buf != NULL); addr = ntohl(a.s_addr); return snprintf(buf, buflen, "%d.%d.%d.%d", (addr >> 24), (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); } /* ** MT_LUA_READER -- "read" a script and make it available to Lua ** ** Parameters: ** l -- Lua state ** data -- pointer to a Lua I/O structure ** size -- size (returned) ** ** Return value: ** Pointer to the data. */ const char * mt_lua_reader(lua_State *l, void *data, size_t *size) { struct mt_lua_io *io; assert(l != NULL); assert(data != NULL); assert(size != NULL); io = (struct mt_lua_io *) data; if (io->lua_io_done) { *size = 0; return NULL; } else if (io->lua_io_script != NULL) { io->lua_io_done = TRUE; *size = io->lua_io_scriptlen; return io->lua_io_script; } else { size_t rlen; memset(scriptbuf, '\0', sizeof scriptbuf); if (feof(stdin)) { *size = 0; io->lua_io_done = TRUE; return NULL; } rlen = fread(scriptbuf, 1, sizeof scriptbuf, stdin); *size = rlen; return (const char *) scriptbuf; } } /* ** MT_LUA_ALLOC -- allocate memory ** ** Parameters: ** ud -- context (not used) ** ptr -- pointer (for realloc()) ** osize -- old size ** nsize -- new size ** ** Return value: ** Allocated memory, or NULL on failure. */ void * mt_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { if (nsize == 0 && osize != 0) { free(ptr); return NULL; } else if (nsize != 0 && osize == 0) { return malloc(nsize); } else { return realloc(ptr, nsize); } } /* ** MT_FLUSH_EOMREQS -- free EOM requests ** ** Parameters: ** ctx -- mt_context handle ** ** Return value: ** None. */ void mt_flush_eomreqs(struct mt_context *ctx) { struct mt_eom_request *r; assert(ctx != NULL); while (ctx->ctx_eomreqs != NULL) { r = ctx->ctx_eomreqs; if (r->eom_rdata != NULL) free(r->eom_rdata); ctx->ctx_eomreqs = r->eom_next; free(r); } } /* ** MT_EOM_REQUEST -- record a request received during EOM ** ** Parameters: ** ctx -- mt_context handle ** cmd -- command received ** len -- length of data ** data -- data received (i.e. request parameters) ** ** Return value: ** TRUE iff addition was successful. */ _Bool mt_eom_request(struct mt_context *ctx, char cmd, size_t len, char *data) { struct mt_eom_request *r; assert(ctx != NULL); r = (struct mt_eom_request *) malloc(sizeof *r); if (r == NULL) return FALSE; r->eom_request = cmd; r->eom_rlen = len; r->eom_rdata = malloc(len); if (r->eom_rdata == NULL) { free(r); return FALSE; } memcpy(r->eom_rdata, data, len); r->eom_next = ctx->ctx_eomreqs; ctx->ctx_eomreqs = r; return TRUE; } /* ** MT_MILTER_READ -- read from a connected filter ** ** Parameters: ** fd -- descriptor to which to write ** cmd -- milter command received (returned) ** buf -- where to write data ** buflen -- bytes available at "buf" (updated) ** ** Return value: ** TRUE iff successful. */ _Bool mt_milter_read(int fd, char *cmd, const char *buf, size_t *len) { int i; int expl; size_t rlen; fd_set fds; struct timeval timeout; char data[MILTER_LEN_BYTES + 1]; assert(fd >= 0); FD_ZERO(&fds); FD_SET(fd, &fds); timeout.tv_sec = tmo; timeout.tv_usec = 0; i = select(fd + 1, &fds, NULL, NULL, &timeout); if (i == 0) { fprintf(stderr, "%s: select(): timeout on fd %d\n", progname, fd); return FALSE; } else if (i == -1) { fprintf(stderr, "%s: select(): fd %d: %s\n", progname, fd, strerror(errno)); return FALSE; } rlen = read(fd, data, sizeof data); if (rlen != sizeof data) { fprintf(stderr, "%s: read(%d): returned %ld, expected %ld\n", progname, fd, (long) rlen, (long) sizeof data); return FALSE; } *cmd = data[MILTER_LEN_BYTES]; data[MILTER_LEN_BYTES] = '\0'; (void) memcpy(&i, data, MILTER_LEN_BYTES); expl = ntohl(i) - 1; rlen = 0; if (expl > 0) { rlen = read(fd, (void *) buf, expl); if (rlen != expl) { fprintf(stderr, "%s: read(%d): returned %ld, expected %ld\n", progname, fd, (long) rlen, (long) expl); return FALSE; } } if (verbose > 1) { fprintf(stdout, "%s: mt_milter_read(%d): cmd %c, len %ld\n", progname, fd, *cmd, (long) rlen); } *len = rlen; return (expl == rlen); } /* ** MT_MILTER_WRITE -- write to a connected filter ** ** Parameters: ** fd -- descriptor to which to write ** cmd -- command to send (an SMFIC_* constant) ** buf -- command data (or NULL) ** len -- length of data at "buf" ** ** Return value: ** TRUE iff successful. */ _Bool mt_milter_write(int fd, int cmd, const char *buf, size_t len) { char command = (char) cmd; ssize_t sl, i; int num_vectors; uint32_t nl; char data[MILTER_LEN_BYTES + 1]; struct iovec vector[2]; assert(fd >= 0); if (verbose > 1) { fprintf(stdout, "%s: mt_milter_write(%d): cmd %c, len %ld\n", progname, fd, command, (long) len); } nl = htonl(len + 1); (void) memcpy(data, (char *) &nl, MILTER_LEN_BYTES); data[MILTER_LEN_BYTES] = command; sl = MILTER_LEN_BYTES + 1; /* set up the vector for the size / command */ vector[0].iov_base = (void *) data; vector[0].iov_len = sl; /* ** Determine if there is command data. If so, there will be two ** vectors. If not, there will be only one. The vectors are set ** up here and 'num_vectors' and 'sl' are set appropriately. */ if (len <= 0 || buf == NULL) { num_vectors = 1; } else { num_vectors = 2; sl += len; vector[1].iov_base = (void *) buf; vector[1].iov_len = len; } /* write the vector(s) */ i = writev(fd, vector, num_vectors); if (i != sl) { fprintf(stderr, "%s: writev(%d): returned %ld, expected %ld\n", progname, fd, (long) i, (long) sl); } return (i == sl); } /* ** MT_ASSERT_STATE -- bring a connection up to a given state ** ** Parameters: ** ctx -- miltertest context ** state -- desired state ** ** Return value: ** TRUE if successful, FALSE otherwise. */ _Bool mt_assert_state(struct mt_context *ctx, int state) { size_t len; size_t s; uint16_t port; char buf[BUFRSZ]; assert(ctx != NULL); if (state >= STATE_NEGOTIATED && ctx->ctx_state < STATE_NEGOTIATED) { char rcmd; size_t buflen; uint32_t mta_version; uint32_t mta_protoopts; uint32_t mta_actions; uint32_t nvers; uint32_t npopts; uint32_t nacts; buflen = sizeof buf; mta_version = SMFI_PROT_VERSION; mta_protoopts = SMFI_CURR_PROT; mta_actions = SMFI_CURR_ACTS; nvers = htonl(mta_version); nacts = htonl(mta_actions); npopts = htonl(mta_protoopts); (void) memcpy(buf, (char *) &nvers, MILTER_LEN_BYTES); (void) memcpy(buf + MILTER_LEN_BYTES, (char *) &nacts, MILTER_LEN_BYTES); (void) memcpy(buf + (MILTER_LEN_BYTES * 2), (char *) &npopts, MILTER_LEN_BYTES); if (!mt_milter_write(ctx->ctx_fd, SMFIC_OPTNEG, buf, MILTER_OPTLEN)) return FALSE; if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; if (rcmd != SMFIC_OPTNEG) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to option negotiation on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; return FALSE; } /* decode and store requested protocol steps and actions */ (void) memcpy((char *) &nvers, buf, MILTER_LEN_BYTES); (void) memcpy((char *) &nacts, buf + MILTER_LEN_BYTES, MILTER_LEN_BYTES); (void) memcpy((char *) &npopts, buf + (MILTER_LEN_BYTES * 2), MILTER_LEN_BYTES); ctx->ctx_mactions = ntohl(nacts); ctx->ctx_mpopts = ntohl(npopts); ctx->ctx_state = STATE_NEGOTIATED; } if (state >= STATE_CONNINFO && ctx->ctx_state < STATE_CONNINFO) { if (!CHECK_MPOPTS(ctx, SMFIP_NOCONNECT)) { char rcmd; size_t buflen; buflen = sizeof buf; port = htons(DEFCLIENTPORT); len = strlcpy(buf, DEFCLIENTHOST, sizeof buf); buf[len++] = '\0'; buf[len++] = '4'; /* IPv4 only for now */ memcpy(&buf[len], &port, sizeof port); len += sizeof port; memcpy(&buf[len], DEFCLIENTIP, strlen(DEFCLIENTIP) + 1); s = len + strlen(DEFCLIENTIP) + 1; if (!mt_milter_write(ctx->ctx_fd, SMFIC_CONNECT, buf, s)) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_CONN)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to connection information on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_CONNINFO; } if (state >= STATE_HELO && ctx->ctx_state < STATE_HELO) { if (!CHECK_MPOPTS(ctx, SMFIP_NOHELO)) { char rcmd; size_t buflen; buflen = sizeof buf; len = strlcpy(buf, DEFCLIENTHOST, sizeof buf); buf[len++] = '\0'; if (!mt_milter_write(ctx->ctx_fd, SMFIC_HELO, buf, len)) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_HELO)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to HELO on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_HELO; } if (state >= STATE_ENVFROM && ctx->ctx_state < STATE_ENVFROM) { if (!CHECK_MPOPTS(ctx, SMFIP_NOMAIL)) { char rcmd; size_t buflen; buflen = sizeof buf; len = strlcpy(buf, DEFSENDER, sizeof buf); buf[len++] = '\0'; if (!mt_milter_write(ctx->ctx_fd, SMFIC_MAIL, buf, len)) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_MAIL)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to MAIL on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_ENVFROM; } if (state >= STATE_ENVRCPT && ctx->ctx_state < STATE_ENVRCPT) { if (!CHECK_MPOPTS(ctx, SMFIP_NORCPT)) { char rcmd; size_t buflen; buflen = sizeof buf; len = strlcpy(buf, DEFRECIPIENT, sizeof buf); buf[len++] = '\0'; if (!mt_milter_write(ctx->ctx_fd, SMFIC_RCPT, buf, len)) return FALSE; rcmd = SMFIR_CONTINUE; if ((ctx->ctx_mpopts & SMFIP_NR_RCPT) == 0) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to RCPT on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_ENVRCPT; } if (state >= STATE_DATA && ctx->ctx_state < STATE_DATA) { #ifdef SMFIC_DATA if (!CHECK_MPOPTS(ctx, SMFIP_NODATA)) { char rcmd; size_t buflen; buflen = sizeof buf; if (!mt_milter_write(ctx->ctx_fd, SMFIC_DATA, NULL, 0)) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_DATA)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to DATA on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } #endif /* SMFIC_DATA */ ctx->ctx_state = STATE_DATA; } if (state >= STATE_HEADER && ctx->ctx_state < STATE_HEADER) { if (!CHECK_MPOPTS(ctx, SMFIP_NOHDRS)) { char rcmd; size_t buflen; buflen = sizeof buf; len = strlcpy(buf, DEFHEADERNAME, sizeof buf); buf[len++] = '\0'; len += strlcpy(buf + len, DEFSENDER, sizeof buf - len); buf[len++] = '\0'; if (!mt_milter_write(ctx->ctx_fd, SMFIC_HEADER, buf, len)) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_HDR)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to header on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_HEADER; } if (state >= STATE_EOH && ctx->ctx_state < STATE_EOH) { if (!CHECK_MPOPTS(ctx, SMFIP_NOEOH)) { char rcmd; size_t buflen; buflen = sizeof buf; if (!mt_milter_write(ctx->ctx_fd, SMFIC_EOH, NULL, 0)) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_EOH)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to EOH on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_EOH; } if (state >= STATE_BODY && ctx->ctx_state < STATE_BODY) { if (!CHECK_MPOPTS(ctx, SMFIP_NOBODY)) { char rcmd; size_t buflen; buflen = sizeof buf; if (!mt_milter_write(ctx->ctx_fd, SMFIC_BODY, DEFBODY, strlen(DEFBODY))) return FALSE; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_BODY)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) return FALSE; ctx->ctx_response = rcmd; } if (rcmd != SMFIR_CONTINUE) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to body on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; } } ctx->ctx_state = STATE_BODY; } return TRUE; } /* ** MT_ECHO -- echo a string ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_echo(lua_State *l) { char *str; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_isstring(l, 1)) { lua_pushstring(l, "mt.echo(): Invalid argument"); lua_error(l); } str = (char *) lua_tostring(l, 1); lua_pop(l, 1); fprintf(stdout, "%s\n", str); return 0; } /* ** MT_CHDIR -- change working directory ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_chdir(lua_State *l) { char *str; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_isstring(l, 1)) { lua_pushstring(l, "mt.chdir(): Invalid argument"); lua_error(l); } str = (char *) lua_tostring(l, 1); lua_pop(l, 1); if (chdir(str) != 0) { lua_pushfstring(l, "mt.chdir(): %s: %s", str, strerror(errno)); lua_error(l); } if (verbose > 1) fprintf(stderr, "%s: now in directory %s\n", progname, str); return 0; } /* ** MT_GETCWD -- get current working directory ** ** Parameters: ** l -- Lua state ** ** Return value: ** String containing current working directory. */ int mt_getcwd(lua_State *l) { char dir[MAXPATHLEN + 1]; assert(l != NULL); if (lua_gettop(l) != 0) { lua_pushstring(l, "mt.getcwd(): Invalid argument"); lua_error(l); } memset(dir, '\0', sizeof dir); if (getcwd(dir, MAXPATHLEN) == NULL) { lua_pushstring(l, "mt.getcwd(): getcwd() returned error"); lua_error(l); } lua_pushstring(l, dir); return 1; } /* ** MT_SET_TIMEOUT -- set read timeout ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_set_timeout(lua_State *l) { assert(l != NULL); if (lua_gettop(l) != 1 || !lua_isnumber(l, 1)) { lua_pushstring(l, "mt.set_timeout(): Invalid argument"); lua_error(l); } tmo = (unsigned int) lua_tonumber(l, 1); lua_pop(l, 1); return 0; } /* ** MT_STARTFILTER -- start a filter ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_startfilter(lua_State *l) { const char **argv; int c; int status; int args; int fds[2]; pid_t child; assert(l != NULL); args = lua_gettop(l); if (args < 1) { lua_pushstring(l, "mt.startfilter(): Invalid argument"); lua_error(l); } for (c = 1; c <= args; c++) { if (!lua_isstring(l, c)) { lua_pushstring(l, "mt.startfilter(): Invalid argument"); lua_error(l); } } argv = (const char **) malloc(sizeof(char *) * (args + 1)); if (argv == NULL) { lua_pushfstring(l, "mt.startfilter(): malloc(): %s", strerror(errno)); lua_error(l); } for (c = 1; c <= args; c++) { argv[c - 1] = lua_tostring(l, c); if (verbose > 2) { fprintf(stderr, "%s: argv[%d] = `%s'\n", progname, c - 1, argv[c - 1]); } } argv[c - 1] = NULL; lua_pop(l, c); if (pipe(fds) != 0) { lua_pushfstring(l, "mt.startfilter(): pipe(): %s", strerror(errno)); lua_error(l); } if (fcntl(fds[1], F_SETFD, FD_CLOEXEC) != 0) { lua_pushfstring(l, "mt.startfilter(): fcntl(): %s", strerror(errno)); lua_error(l); } child = fork(); switch (child) { case -1: lua_pushfstring(l, "mt.startfilter(): fork(): %s", strerror(errno)); lua_error(l); case 0: close(fds[0]); execv(argv[0], (char * const *) argv); exit(1); default: close(fds[1]); c = read(fds[0], &args, sizeof(args)); if (c == -1) { lua_pushfstring(l, "mt.startfilter(): read(): %s", strerror(errno)); lua_error(l); } else if (c != 0) { lua_pushfstring(l, "mt.startfilter(): read(): got %d, expecting 0", c); lua_error(l); } close(fds[0]); filterpid = child; child = wait4(filterpid, &status, WNOHANG, NULL); if (child != 0) { lua_pushfstring(l, "mt.startfilter(): wait4(): child %d exited prematurely, status %d", child, status); lua_error(l); } if (verbose > 0) { fprintf(stderr, "%s: '%s' started in process %d\n", progname, argv[0], filterpid); } free((void *) argv); break; } lua_pushnil(l); return 1; } /* ** MT_SIGNAL -- signal a filter ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_signal(lua_State *l) { int signum; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_isnumber(l, 1)) { lua_pushstring(l, "mt.signal(): Invalid argument"); lua_error(l); } signum = lua_tonumber(l, 1); lua_pop(l, 1); if (filterpid <= 1) { lua_pushstring(l, "mt.signal(): Filter not running"); lua_error(l); } if (kill(filterpid, signum) != 0) { lua_pushfstring(l, "mt.signal(): kill(): %s", strerror(errno)); lua_error(l); } if (verbose > 0) fprintf(stderr, "%s: sent signal %d\n", progname, signum); lua_pushnil(l); return 1; } /* ** MT_CONNECT -- connect to a filter, returning a handle ** ** Parameters: ** l -- Lua state ** ** Return value: ** A new connection handle (on the Lua stack). */ int mt_connect(lua_State *l) { int top; int af; int fd = -1; int saverr = 0; u_int count = 1; useconds_t interval = 0; char *at; char *p; const char *sockinfo; struct mt_context *new; assert(l != NULL); top = lua_gettop(l); if (!(top == 1 && lua_isstring(l, 1)) && !(top == 3 && lua_isstring(l, 1) && lua_isnumber(l, 2) && lua_isnumber(l, 3))) { lua_pushstring(l, "mt.connect(): Invalid argument"); lua_error(l); } sockinfo = lua_tostring(l, 1); if (top == 3) { char *f; count = (u_int) lua_tonumber(l, 2); interval = (useconds_t) (1000000. * lua_tonumber(l, 3)); f = getenv("MILTERTEST_RETRY_SPEED_FACTOR"); if (f != NULL) { unsigned int factor; factor = strtoul(f, &p, 10); if (*p == '\0') interval *= factor; } } lua_pop(l, top); af = AF_UNSPEC; p = strchr(sockinfo, ':'); if (p == NULL) { af = AF_UNIX; } else { *p = '\0'; if (strcasecmp(sockinfo, "inet") == 0) af = AF_INET; else if (strcasecmp(sockinfo, "unix") == 0 || strcasecmp(sockinfo, "local") == 0) af = AF_UNIX; *p = ':'; } if (af == AF_UNSPEC) { lua_pushstring(l, "mt.connect(): Invalid argument"); lua_error(l); } switch (af) { case AF_UNIX: { struct sockaddr_un sa; memset(&sa, '\0', sizeof sa); sa.sun_family = AF_UNIX; #ifdef HAVE_SUN_LEN sa.sun_len = sizeof sa; #endif /* HAVE_SUN_LEN */ if (p == NULL) strlcpy(sa.sun_path, sockinfo, sizeof sa.sun_path); else strlcpy(sa.sun_path, p + 1, sizeof sa.sun_path); while (count > 0) { fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { lua_pushfstring(l, "mt.connect(): socket(): %s", strerror(errno)); lua_error(l); } saverr = 0; if (connect(fd, (struct sockaddr *) &sa, sizeof sa) == 0) break; saverr = errno; if (verbose > 1) { fprintf(stdout, "%s: connect(): %s; %u tr%s left\n", progname, strerror(errno), count - 1, count == 2 ? "y" : "ies"); } close(fd); usleep(interval); count--; } if (saverr != 0) { lua_pushfstring(l, "mt.connect(): %s: connect(): %s", sockinfo, strerror(errno)); lua_error(l); } break; } case AF_INET: { struct servent *srv; struct sockaddr_in sa; memset(&sa, '\0', sizeof sa); sa.sin_family = AF_INET; p++; at = strchr(p, '@'); if (at == NULL) { sa.sin_addr.s_addr = INADDR_ANY; } else { struct hostent *h; *at = '\0'; h = gethostbyname(at + 1); if (h != NULL) { memcpy(&sa.sin_addr.s_addr, h->h_addr, sizeof sa.sin_addr.s_addr); } else { sa.sin_addr.s_addr = inet_addr(at + 1); } } srv = getservbyname(p, "tcp"); if (srv != NULL) { sa.sin_port = srv->s_port; } else { int port; char *q; port = strtoul(p, &q, 10); if (*q != '\0') { lua_pushstring(l, "mt.connect(): Invalid argument"); lua_error(l); } sa.sin_port = htons(port); } if (at != NULL) *at = '@'; while (count > 0) { fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { lua_pushfstring(l, "mt.connect(): socket(): %s", strerror(errno)); lua_error(l); } saverr = 0; if (connect(fd, (struct sockaddr *) &sa, sizeof sa) == 0) break; saverr = errno; if (verbose > 1) { fprintf(stdout, "%s: connect(): %s; %u tr%s left\n", progname, strerror(errno), count - 1, count == 2 ? "y" : "ies"); } close(fd); usleep(interval); count--; } if (saverr != 0) { lua_pushfstring(l, "mt.connect(): %s: connect(): %s", sockinfo, strerror(errno)); lua_error(l); } break; } default: assert(0); } new = (struct mt_context *) malloc(sizeof *new); if (new == NULL) { lua_pushfstring(l, "mt.connect(): malloc(): %s", strerror(errno)); lua_error(l); } new->ctx_state = STATE_INIT; new->ctx_fd = fd; new->ctx_response = '\0'; new->ctx_eomreqs = NULL; new->ctx_mactions = 0; new->ctx_mpopts = 0; lua_pushlightuserdata(l, new); if (verbose > 0) { fprintf(stdout, "%s: connected to '%s', fd %d\n", progname, sockinfo, fd); } return 1; } /* ** MT_SLEEP -- sleep ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_sleep(lua_State *l) { double p; useconds_t usecs; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_isnumber(l, 1)) { lua_pushstring(l, "mt.sleep(): Invalid argument"); lua_error(l); } p = lua_tonumber(l, 1); usecs = (useconds_t) (1000000. * p); lua_pop(l, 1); if (verbose > 1) { fprintf(stdout, "%s: pausing for %f second%s\n", progname, p, usecs == 1000000 ? "" : "s"); } usleep(usecs); lua_pushnil(l); return 1; } /* ** MT_DISCONNECT -- disconnect from a filter ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_disconnect(lua_State *l) { _Bool polite = TRUE; int top; struct mt_context *ctx; assert(l != NULL); top = lua_gettop(l); if ((top != 1 && top != 2) || !lua_islightuserdata(l, 1) || (top == 2 && !lua_isboolean(l, 2))) { lua_pushstring(l, "mt.disconnect(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); if (top == 2) polite = lua_toboolean(l, 2); lua_pop(l, top); if (polite) (void) mt_milter_write(ctx->ctx_fd, SMFIC_QUIT, NULL, 0); (void) close(ctx->ctx_fd); if (verbose > 0) { fprintf(stdout, "%s: disconnected fd %d\n", progname, ctx->ctx_fd); } free(ctx); lua_pushnil(l); return 1; } /* ** MT_TEST_ACTION -- send an action bit ** ** Parameters: ** l -- Lua state ** ** Return value: ** Boolean (true/false) */ int mt_test_action(lua_State *l) { struct mt_context *ctx; unsigned long action; assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "mt.test_action(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); action = lua_tonumber(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_NEGOTIATED)) lua_error(l); lua_pushboolean(l, (ctx->ctx_mactions & action) != 0); return 1; } /* ** MT_TEST_OPTION -- send a protocol option bit ** ** Parameters: ** l -- Lua state ** ** Return value: ** Boolean (true/false) */ int mt_test_option(lua_State *l) { unsigned long option; struct mt_context *ctx; assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "mt.test_option(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); option = lua_tonumber(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_NEGOTIATED)) lua_error(l); lua_pushboolean(l, (ctx->ctx_mpopts & option) != 0); return 1; } /* ** MT_NEGOTIATE -- option negotiation ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_negotiate(lua_State *l) { char rcmd; size_t buflen; uint32_t mta_version; uint32_t mta_protoopts; uint32_t mta_actions; uint32_t nvers; uint32_t npopts; uint32_t nacts; struct mt_context *ctx; char buf[BUFRSZ]; if (lua_gettop(l) != 4 || !lua_islightuserdata(l, 1) || (!lua_isnil(l, 2) && !lua_isnumber(l, 2)) || (!lua_isnil(l, 3) && !lua_isnumber(l, 3)) || (!lua_isnil(l, 4) && !lua_isnumber(l, 4))) { lua_pushstring(l, "mt.negotiate(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); buflen = sizeof buf; if (lua_isnumber(l, 2)) mta_version = lua_tonumber(l, 2); else mta_version = SMFI_PROT_VERSION; if (lua_isnumber(l, 3)) mta_protoopts = lua_tonumber(l, 3); else mta_protoopts = SMFI_CURR_PROT; if (lua_isnumber(l, 4)) mta_actions = lua_tonumber(l, 4); else mta_actions = SMFI_CURR_ACTS; lua_pop(l, lua_gettop(l)); nvers = htonl(mta_version); nacts = htonl(mta_actions); npopts = htonl(mta_protoopts); (void) memcpy(buf, (char *) &nvers, MILTER_LEN_BYTES); (void) memcpy(buf + MILTER_LEN_BYTES, (char *) &nacts, MILTER_LEN_BYTES); (void) memcpy(buf + (MILTER_LEN_BYTES * 2), (char *) &npopts, MILTER_LEN_BYTES); if (!mt_milter_write(ctx->ctx_fd, SMFIC_OPTNEG, buf, MILTER_OPTLEN)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } if (rcmd != SMFIC_OPTNEG) { if (verbose > 0) { fprintf(stdout, "%s: filter returned status %d to option negotiation on fd %d\n", progname, rcmd, ctx->ctx_fd); } ctx->ctx_state = STATE_DEAD; lua_pushnil(l); return 1; } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_NEGOTIATED; /* decode and store requested protocol steps and actions */ (void) memcpy((char *) &nvers, buf, MILTER_LEN_BYTES); (void) memcpy((char *) &nacts, buf + MILTER_LEN_BYTES, MILTER_LEN_BYTES); (void) memcpy((char *) &npopts, buf + (MILTER_LEN_BYTES * 2), MILTER_LEN_BYTES); ctx->ctx_mactions = ntohl(nacts); ctx->ctx_mpopts = ntohl(npopts); if (verbose > 0) { fprintf(stdout, "%s: option negotiation sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_MACRO -- send a macro ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_macro(lua_State *l) { int type; int top; int n = 0; int c; size_t s; struct mt_context *ctx; char *bp; char *name; char *value; char buf[BUFRSZ]; assert(l != NULL); top = lua_gettop(l); if (top < 4 || !lua_islightuserdata(l, 1) || !lua_isnumber(l, 2) || !lua_isstring(l, 3) || !lua_isstring(l, 4)) { lua_pushstring(l, "mt.macro(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); type = lua_tonumber(l, 2); if (!mt_assert_state(ctx, STATE_NEGOTIATED)) lua_error(l); s = 1; buf[0] = type; bp = buf + 1; for (c = 3; c < top; c += 2) { if (c + 1 > top || !lua_isstring(l, c) || !lua_isstring(l, c + 1)) { lua_pop(l, top); lua_pushstring(l, "mt.macro(): Invalid argument"); lua_error(l); } name = (char *) lua_tostring(l, c); value = (char *) lua_tostring(l, c + 1); if (strlen(name) + strlen(value) + 2 + bp > buf + sizeof buf) { lua_pop(l, top); lua_pushstring(l, "mt.macro(): Buffer overflow"); lua_error(l); } memcpy(bp, name, strlen(name) + 1); bp += strlen(name) + 1; memcpy(bp, value, strlen(value) + 1); bp += strlen(value) + 1; s += strlen(name) + 1 + strlen(value) + 1; n++; } lua_pop(l, top); if (!mt_milter_write(ctx->ctx_fd, SMFIC_MACRO, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } if (verbose > 0) { fprintf(stdout, "%s: %d '%c' macro(s) sent on fd %d\n", progname, n, type, ctx->ctx_fd); } lua_pushnil(l); return 1; } /* ** MT_CONNINFO -- send connection information ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_conninfo(lua_State *l) { char rcmd; char family = 'U'; size_t buflen; size_t s; uint16_t port; struct mt_context *ctx; char *host; char *bp; char *ipstr; char buf[BUFRSZ]; char tmp[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 3 || !lua_islightuserdata(l, 1) || (!lua_isnil(l, 2) && !lua_isstring(l, 2)) || (!lua_isnil(l, 3) && !lua_isstring(l, 3))) { lua_pushstring(l, "mt.conninfo(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); if (lua_isstring(l, 2)) host = (char *) lua_tostring(l, 2); else host = DEFCLIENTHOST; if (lua_isstring(l, 3)) ipstr = (char *) lua_tostring(l, 3); else ipstr = NULL; lua_pop(l, 3); if (!mt_assert_state(ctx, STATE_NEGOTIATED)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOCONNECT)) { lua_pushstring(l, "mt.conninfo(): negotiated SMFIP_NOCONNECT"); lua_error(l); } if (ipstr == NULL) { #if (HAVE_GETADDRINFO && HAVE_INET_NTOP) char *a = NULL; struct addrinfo *res; struct sockaddr_in *s4; struct sockaddr_in6 *s6; if (getaddrinfo(host, NULL, NULL, &res) != 0) { lua_pushfstring(l, "mt.conninfo(): host '%s' unknown", host); lua_error(l); } if (res->ai_family == AF_INET) { s4 = (struct sockaddr_in *) res->ai_addr; a = (char *) &s4->sin_addr; family = '4'; } else if (res->ai_family == AF_INET6) { s6 = (struct sockaddr_in6 *) res->ai_addr; a = (char *) &s6->sin6_addr; family = '6'; } if (family != 'U') { memset(tmp, '\0', sizeof tmp); if (inet_ntop(res->ai_family, a, tmp, sizeof tmp - 1) == NULL) { freeaddrinfo(res); lua_pushfstring(l, "mt.conninfo(): can't convert address for host '%s' to text", host); lua_error(l); } } freeaddrinfo(res); ipstr = tmp; #else /* HAVE_GETADDRINFO && HAVE_INET_NTOP */ struct hostent *h; struct in_addr sa; h = gethostbyname(host); if (h == NULL) { lua_pushfstring(l, "mt.conninfo(): host '%s' unknown", host); lua_error(l); } memcpy(&sa.s_addr, h->h_addr, sizeof sa.s_addr); mt_inet_ntoa(sa, tmp, sizeof tmp); ipstr = tmp; family = '4'; #endif /* HAVE_GETADDRINFO && HAVE_INET_NTOP */ } else if (strcasecmp(ipstr, "unspec") != 0) { #ifdef HAVE_INET_PTON struct in_addr a; struct in6_addr a6; if (inet_pton(AF_INET6, ipstr, &a6.s6_addr) == 1) { family = '6'; } else if (inet_pton(AF_INET, ipstr, &a.s_addr) == 1) { family = '4'; } else { lua_pushfstring(l, "mt.conninfo(): invalid IP address '%s'", ipstr); lua_error(l); } #else /* HAVE_INET_PTON */ struct in_addr sa; sa.s_addr = inet_addr(ipstr); if (sa.s_addr == INADDR_NONE) { lua_pushfstring(l, "mt.conninfo(): invalid IPv4 address '%s'", ipstr); lua_error(l); } family = '4'; #endif /* HAVE_INET_PTON */ } bp = buf; memcpy(bp, host, strlen(host)); bp += strlen(host); *bp++ = '\0'; memcpy(bp, &family, sizeof family); bp += sizeof family; s = strlen(host) + 1 + sizeof(char); if (family != 'U') /* known family data */ { port = htons(DEFCLIENTPORT); /* don't really need this */ memcpy(bp, &port, sizeof port); bp += sizeof port; memcpy(bp, ipstr, strlen(ipstr) + 1); s += sizeof port + strlen(ipstr) + 1; } if (!mt_milter_write(ctx->ctx_fd, SMFIC_CONNECT, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_CONN)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_CONNINFO; if (verbose > 0) { fprintf(stdout, "%s: connection details sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_UNKNOWN -- send unknown command information ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_unknown(lua_State *l) { #ifdef SMFIC_UNKNOWN char rcmd; size_t buflen; size_t s; struct mt_context *ctx; char *cmd; char *bp; char buf[BUFRSZ]; #endif /* SMFIC_UNKNOWN */ assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "mt.unknown(): Invalid argument"); lua_error(l); } #ifndef SMFIC_UNKNOWN lua_pushstring(l, "mt.unknown(): Operation not supported"); lua_error(l); #else /* ! SMFIC_UNKNOWN */ ctx = (struct mt_context *) lua_touserdata(l, 1); cmd = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_CONNINFO)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOUNKNOWN)) { lua_pushstring(l, "mt.unknown(): negotiated SMFIP_NOUNKNOWN"); lua_error(l); } s = strlen(cmd) + 1; bp = buf; memcpy(bp, cmd, strlen(cmd)); bp += strlen(cmd); *bp++ = '\0'; if (!mt_milter_write(ctx->ctx_fd, SMFIC_UNKNOWN, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_UNKN)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; if (verbose > 0) { fprintf(stdout, "%s: UNKNOWN sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); #endif /* ! SMFIC_UNKNOWN */ return 1; } /* ** MT_HELO -- send HELO information ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_helo(lua_State *l) { char rcmd; size_t buflen; size_t s; struct mt_context *ctx; char *host; char *bp; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "mt.helo(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); host = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_CONNINFO)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOHELO)) { lua_pushstring(l, "mt.helo(): negotiated SMFIP_NOHELO"); lua_error(l); } s = strlen(host) + 1; bp = buf; memcpy(bp, host, strlen(host)); bp += strlen(host); *bp++ = '\0'; if (!mt_milter_write(ctx->ctx_fd, SMFIC_HELO, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_HELO)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_HELO; if (verbose > 0) { fprintf(stdout, "%s: HELO sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_MAILFROM -- send MAIL FROM information ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_mailfrom(lua_State *l) { char rcmd; int c; size_t buflen; size_t s; char *p; char *bp; struct mt_context *ctx; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) < 2 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.mailfrom(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); s = 0; bp = buf; for (c = 2; c <= lua_gettop(l); c++) { p = (char *) lua_tostring(l, c); s += strlen(p) + 1; memcpy(bp, p, strlen(p) + 1); bp += strlen(p) + 1; /* XXX -- watch for overruns */ } lua_pop(l, lua_gettop(l)); if (!mt_assert_state(ctx, STATE_HELO)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOMAIL)) { lua_pushstring(l, "mt.mailfrom(): negotiated SMFIP_NOMAIL"); lua_error(l); } if (!mt_milter_write(ctx->ctx_fd, SMFIC_MAIL, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_MAIL)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_ENVFROM; mt_flush_eomreqs(ctx); if (verbose > 0) { fprintf(stdout, "%s: MAIL sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_RCPTTO -- send RCPT TO information ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_rcptto(lua_State *l) { char rcmd; int c; size_t buflen; size_t s; char *p; char *bp; char *end; struct mt_context *ctx; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) < 2 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.rcptto(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); s = 0; bp = buf; end = bp + sizeof buf; memset(buf, '\0', sizeof buf); for (c = 2; c <= lua_gettop(l); c++) { p = (char *) lua_tostring(l, c); s += strlen(p) + 1; if (bp + strlen(p) >= end) { lua_pushstring(l, "mt.rcptto(): Input overflow"); lua_error(l); } memcpy(bp, p, strlen(p) + 1); bp += strlen(p) + 1; } lua_pop(l, lua_gettop(l)); if (!mt_assert_state(ctx, STATE_ENVFROM)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NORCPT)) { lua_pushstring(l, "mt.rcptto(): negotiated SMFIP_NORCPT"); lua_error(l); } if (!mt_milter_write(ctx->ctx_fd, SMFIC_RCPT, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_RCPT)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_ENVRCPT; if (verbose > 0) { fprintf(stdout, "%s: RCPT sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_DATA -- send DATA notice ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_data(lua_State *l) { #ifdef SMFIC_DATA char rcmd; size_t buflen; struct mt_context *ctx; char buf[BUFRSZ]; #endif /* SMFIC_DATA */ assert(l != NULL); if (lua_gettop(l) != 1 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.data(): Invalid argument"); lua_error(l); } #ifndef SMFIC_DATA lua_pushstring(l, "mt.ata(): Operation not supported"); lua_error(l); #else /* ! SMFIC_DATA */ ctx = (struct mt_context *) lua_touserdata(l, 1); lua_pop(l, 1); if (!mt_assert_state(ctx, STATE_DATA)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NODATA)) { lua_pushstring(l, "mt.data(): negotiated SMFIP_NODATA"); lua_error(l); } if (!mt_milter_write(ctx->ctx_fd, SMFIC_DATA, NULL, 0)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_DATA)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_DATA; if (verbose > 0) { fprintf(stdout, "%s: DATA sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); #endif /* ! SMFIC_DATA */ return 1; } /* ** MT_HEADER -- send header field information ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_header(lua_State *l) { char rcmd; size_t buflen; size_t s; char *bp; char *name; char *value; struct mt_context *ctx; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 3 || !lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isstring(l, 3)) { lua_pushstring(l, "mt.header(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); name = (char *) lua_tostring(l, 2); value = (char *) lua_tostring(l, 3); lua_pop(l, 3); s = strlen(name) + 1 + strlen(value) + 1; #ifdef SMFIP_HDR_LEADSPC if (CHECK_MPOPTS(ctx, SMFIP_HDR_LEADSPC)) s++; #endif /* SMFIP_HDR_LEADSPC */ bp = buf; memcpy(buf, name, strlen(name) + 1); bp += strlen(name) + 1; #ifdef SMFIP_HDR_LEADSPC if (CHECK_MPOPTS(ctx, SMFIP_HDR_LEADSPC)) *bp++ = ' '; #endif /* SMFIP_HDR_LEADSPC */ memcpy(bp, value, strlen(value) + 1); if (!mt_assert_state(ctx, STATE_ENVRCPT)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOHDRS)) { lua_pushstring(l, "mt.header(): negotiated SMFIP_NOHDRS"); lua_error(l); } if (!mt_milter_write(ctx->ctx_fd, SMFIC_HEADER, buf, s)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_HDR)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_HEADER; if (verbose > 0) { fprintf(stdout, "%s: header sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_EOH -- send end-of-header notice ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_eoh(lua_State *l) { char rcmd; size_t buflen; struct mt_context *ctx; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.eoh(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); lua_pop(l, 1); if (!mt_assert_state(ctx, STATE_HEADER)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOEOH)) { lua_pushstring(l, "mt.eoh(): negotiated SMFIP_NOEOH"); lua_error(l); } if (!mt_milter_write(ctx->ctx_fd, SMFIC_EOH, NULL, 0)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_EOH)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_EOH; if (verbose > 0) { fprintf(stdout, "%s: EOH sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_BODYSTRING -- send a string of body ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_bodystring(lua_State *l) { char rcmd; size_t buflen; struct mt_context *ctx; char *str; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "mt.bodystring(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); str = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_EOH)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOBODY)) { lua_pushstring(l, "mt.bodystring(): negotiated SMFIP_NOBODY"); lua_error(l); } if (!mt_milter_write(ctx->ctx_fd, SMFIC_BODY, str, strlen(str))) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_BODY)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_BODY; if (verbose > 0) { fprintf(stdout, "%s: %zu byte(s) of body sent on fd %d, reply '%c'\n", progname, strlen(str), ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_BODYRANDOM -- send a random chunk of body ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_bodyrandom(lua_State *l) { char rcmd; unsigned long rw; unsigned long rl; int c; size_t buflen; struct mt_context *ctx; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "mt.bodyrandom(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); rw = (unsigned long) lua_tonumber(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_EOH)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOBODY)) { lua_pushstring(l, "mt.bodyrandom(): negotiated SMFIP_NOBODY"); lua_error(l); } while (rw > 0) { memset(buf, '\0', sizeof buf); rl = random() % (sizeof buf - 3); if (rl > rw) rl = rw; for (c = 0; c < rl; c++) buf[c] = (random() % 95) + 32; strlcat(buf, "\r\n", sizeof buf); if (!mt_milter_write(ctx->ctx_fd, SMFIC_BODY, buf, strlen(buf))) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof buf; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_BODY)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_BODY; if (verbose > 0) { fprintf(stdout, "%s: %zu byte(s) of body sent on fd %d, reply '%c'\n", progname, strlen(buf), ctx->ctx_fd, rcmd); } if (rcmd != SMFIR_CONTINUE) break; rw -= rl; } lua_pushnil(l); return 1; } /* ** MT_BODYFILE -- send contents of a file as body ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_bodyfile(lua_State *l) { char rcmd; char *file; FILE *f; ssize_t rlen; struct mt_context *ctx; char chunk[CHUNKSZ]; assert(l != NULL); if (lua_gettop(l) != 2 || !lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "mt.bodyfile(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); file = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (!mt_assert_state(ctx, STATE_EOH)) lua_error(l); if (CHECK_MPOPTS(ctx, SMFIP_NOBODY)) { lua_pushstring(l, "mt.bodyfile(): negotiated SMFIP_NOBODY"); lua_error(l); } f = fopen(file, "r"); if (f == NULL) { lua_pushfstring(l, "mt.bodyfile(): %s: fopen(): %s", file, strerror(errno)); lua_error(l); } for (;;) { rlen = fread(chunk, 1, sizeof chunk, f); if (rlen > 0) { size_t buflen; if (!mt_milter_write(ctx->ctx_fd, SMFIC_BODY, chunk, rlen)) { fclose(f); lua_pushstring(l, "mt.milter_write() failed"); return 1; } buflen = sizeof chunk; rcmd = SMFIR_CONTINUE; if (!CHECK_MPOPTS(ctx, SMFIP_NR_BODY)) { if (!mt_milter_read(ctx->ctx_fd, &rcmd, chunk, &buflen)) { fclose(f); lua_pushstring(l, "mt.milter_read() failed"); return 1; } } if (verbose > 0) { fprintf(stdout, "%s: %zu byte(s) of body sent on fd %d, reply '%c'\n", progname, rlen, ctx->ctx_fd, rcmd); } } if (rlen < sizeof chunk || rcmd != SMFIR_CONTINUE) break; } fclose(f); ctx->ctx_response = rcmd; ctx->ctx_state = STATE_BODY; lua_pushnil(l); return 1; } /* ** MT_EOM -- send end-of-message notice, collect requests ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_eom(lua_State *l) { char rcmd; size_t buflen; struct mt_context *ctx; char buf[BUFRSZ]; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.eom(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); lua_pop(l, 1); if (!mt_assert_state(ctx, STATE_BODY)) lua_error(l); if (!mt_milter_write(ctx->ctx_fd, SMFIC_BODYEOB, NULL, 0)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } rcmd = '\0'; for (;;) { buflen = sizeof buf; if (!mt_milter_read(ctx->ctx_fd, &rcmd, buf, &buflen)) { lua_pushstring(l, "mt.milter_read() failed"); return 1; } if (rcmd == SMFIR_CONTINUE || rcmd == SMFIR_ACCEPT || rcmd == SMFIR_REJECT || rcmd == SMFIR_TEMPFAIL || rcmd == SMFIR_DISCARD) break; if (!mt_eom_request(ctx, rcmd, buflen, buflen == 0 ? NULL : buf)) { lua_pushstring(l, "mt.eom_request() failed"); return 1; } if (rcmd == SMFIR_REPLYCODE) break; } ctx->ctx_response = rcmd; ctx->ctx_state = STATE_EOM; if (verbose > 0) { fprintf(stdout, "%s: EOM sent on fd %d, reply '%c'\n", progname, ctx->ctx_fd, rcmd); } lua_pushnil(l); return 1; } /* ** MT_EOM_CHECK -- test for a specific end-of-message action ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_eom_check(lua_State *l) { int op; struct mt_context *ctx; struct mt_eom_request *r; assert(l != NULL); if (lua_gettop(l) < 2 || lua_gettop(l) > 5 || !lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); op = lua_tonumber(l, 2); switch (op) { case MT_HDRADD: { char *name = NULL; char *value = NULL; if (lua_gettop(l) >= 3) { if (!lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } name = (char *) lua_tostring(l, 3); } if (lua_gettop(l) == 4) { if (!lua_isstring(l, 4)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } value = (char *) lua_tostring(l, 4); } if (lua_gettop(l) == 5) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_ADDHEADER) { char *rname; char *rvalue; rname = r->eom_rdata; rvalue = r->eom_rdata + strlen(rname) + 1; if ((name == NULL || strcmp(name, rname) == 0) && (value == NULL || strcmp(value, rvalue) == 0)) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } case MT_HDRINSERT: { #ifdef SMFIR_INSHEADER int idx = -1; char *name = NULL; char *value = NULL; if (lua_gettop(l) >= 3) { if (!lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } name = (char *) lua_tostring(l, 3); } if (lua_gettop(l) >= 4) { if (!lua_isstring(l, 4)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } value = (char *) lua_tostring(l, 4); } if (lua_gettop(l) == 5) { if (!lua_isnumber(l, 5)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } idx = lua_tonumber(l, 5); } lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_INSHEADER) { int ridx; char *rname; char *rvalue; memcpy(&ridx, r->eom_rdata, MILTER_LEN_BYTES); ridx = ntohl(ridx); rname = r->eom_rdata + MILTER_LEN_BYTES; rvalue = r->eom_rdata + MILTER_LEN_BYTES + strlen(rname) + 1; if ((name == NULL || strcmp(name, rname) == 0) && (value == NULL || strcmp(value, rvalue) == 0) && (idx == -1 || ridx == idx)) { lua_pushboolean(l, 1); return 1; } } } #endif /* SMFIR_INSHEADER */ lua_pushboolean(l, 0); return 1; } case MT_HDRCHANGE: { int idx = -1; char *name = NULL; char *value = NULL; if (lua_gettop(l) >= 3) { if (!lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } name = (char *) lua_tostring(l, 3); } if (lua_gettop(l) >= 4) { if (!lua_isstring(l, 4)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } value = (char *) lua_tostring(l, 4); } if (lua_gettop(l) == 5) { if (!lua_isnumber(l, 5)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } idx = lua_tonumber(l, 4); } lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_CHGHEADER) { int ridx; char *rname; char *rvalue; memcpy(&ridx, r->eom_rdata, MILTER_LEN_BYTES); ridx = ntohl(ridx); rname = r->eom_rdata + MILTER_LEN_BYTES; rvalue = r->eom_rdata + MILTER_LEN_BYTES + strlen(rname) + 1; if ((name == NULL || strcmp(name, rname) == 0) && (value == NULL || strcmp(value, rvalue) == 0) && (idx == -1 || ridx == idx)) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } case MT_HDRDELETE: { int idx = -1; char *name = NULL; if (lua_gettop(l) >= 3) { if (!lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } name = (char *) lua_tostring(l, 3); } if (lua_gettop(l) == 4) { if (!lua_isnumber(l, 4)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } idx = lua_tonumber(l, 4); } if (lua_gettop(l) == 5) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_CHGHEADER) { int ridx; char *rname; char *rvalue; memcpy(&ridx, r->eom_rdata, MILTER_LEN_BYTES); ridx = ntohl(ridx); rname = r->eom_rdata + MILTER_LEN_BYTES; rvalue = r->eom_rdata + MILTER_LEN_BYTES + strlen(rname) + 1; if ((name == NULL || strcmp(name, rname) == 0) && rvalue[0] == '\0' && (idx == -1 || ridx == idx)) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } case MT_RCPTADD: { char *rcpt; if (lua_gettop(l) != 3 || !lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } rcpt = (char *) lua_tostring(l, 3); lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_ADDRCPT) { char *rname; rname = r->eom_rdata; if (strcmp(rcpt, rname) == 0) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } case MT_RCPTDELETE: { char *rcpt; if (lua_gettop(l) != 3 || !lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } rcpt = (char *) lua_tostring(l, 3); lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_DELRCPT) { char *rname; rname = r->eom_rdata; if (strcmp(rcpt, rname) == 0) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } case MT_BODYCHANGE: { char *newbody = NULL; if (lua_gettop(l) < 2 || lua_gettop(l) > 3 || (lua_gettop(l) == 3 && !lua_isstring(l, 3))) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } if (lua_gettop(l) == 3) newbody = (char *) lua_tostring(l, 3); lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_REPLBODY) { char *rbody; rbody = r->eom_rdata; if (newbody == NULL || (strlen(newbody) == r->eom_rlen && memcmp(rbody, newbody, r->eom_rlen) == 0)) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } #ifdef SMFIR_QUARANTINE case MT_QUARANTINE: { char *reason = NULL; if (lua_gettop(l) < 2 || lua_gettop(l) > 3 || (lua_gettop(l) == 3 && !lua_isstring(l, 3))) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } if (lua_gettop(l) == 3) reason = (char *) lua_tostring(l, 3); lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_QUARANTINE) { char *rreason; rreason = r->eom_rdata; if (reason == NULL || strcmp(reason, rreason) == 0) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } #endif /* SMFIR_QUARANTINE */ case MT_SMTPREPLY: { char *smtp = NULL; char *esc = NULL; char *text = NULL; if (lua_gettop(l) < 3 || !lua_isstring(l, 3)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } smtp = (char *) lua_tostring(l, 3); if (lua_gettop(l) >= 4) { if (!lua_isstring(l, 4)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } esc = (char *) lua_tostring(l, 4); } if (lua_gettop(l) == 5) { if (!lua_isstring(l, 5)) { lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } text = (char *) lua_tostring(l, 5); } lua_pop(l, lua_gettop(l)); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { if (r->eom_request == SMFIR_REPLYCODE) { char rbuf[BUFRSZ]; snprintf(rbuf, sizeof rbuf, "%s%s%s%s%s", smtp, esc == NULL ? "" : " ", esc, text == NULL ? "" : " ", text); if (strcmp(rbuf, (char *) r->eom_rdata) == 0) { lua_pushboolean(l, 1); return 1; } } } lua_pushboolean(l, 0); return 1; } default: lua_pushstring(l, "mt.eom_check(): Invalid argument"); lua_error(l); } return 1; } /* ** MT_ABORT -- send transaction abort notice ** ** Parameters: ** l -- Lua state ** ** Return value: ** nil (on the Lua stack) */ int mt_abort(lua_State *l) { struct mt_context *ctx; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.abort(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); lua_pop(l, 1); if (!mt_milter_write(ctx->ctx_fd, SMFIC_ABORT, NULL, 0)) { lua_pushstring(l, "mt.milter_write() failed"); return 1; } ctx->ctx_state = STATE_HELO; if (verbose > 0) { fprintf(stdout, "%s: ABORT sent on fd %d\n", progname, ctx->ctx_fd); } lua_pushnil(l); return 1; } /* ** MT_GETREPLY -- get last reply ** ** Parameters: ** l -- Lua state ** ** Return value: ** Last reply received, as an integer (on the Lua stack). */ int mt_getreply(lua_State *l) { struct mt_context *ctx; assert(l != NULL); if (lua_gettop(l) != 1 || !lua_islightuserdata(l, 1)) { lua_pushstring(l, "mt.getreply(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); lua_pop(l, 1); lua_pushnumber(l, ctx->ctx_response); return 1; } /* ** MT_GETHEADER -- retrieve a header field added during EOM ** ** Parameters: ** l -- Lua state ** ** Return value: ** Last reply received, as a string (on the Lua stack). */ int mt_getheader(lua_State *l) { int idx; char *name; struct mt_context *ctx; struct mt_eom_request *r; assert(l != NULL); if (lua_gettop(l) != 3 || !lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isnumber(l, 3)) { lua_pushstring(l, "mt.getheader(): Invalid argument"); lua_error(l); } ctx = (struct mt_context *) lua_touserdata(l, 1); name = (char *) lua_tostring(l, 2); idx = lua_tonumber(l, 3); lua_pop(l, 3); for (r = ctx->ctx_eomreqs; r != NULL; r = r->eom_next) { #ifdef SMFIR_INSHEADER if (r->eom_request == SMFIR_ADDHEADER || r->eom_request == SMFIR_INSHEADER) #else /* SMFIR_INSHEADER */ if (r->eom_request == SMFIR_ADDHEADER) #endif /* SMFIR_INSHEADER */ { char *rname; char *rvalue; #ifdef SMFIR_INSHEADER if (r->eom_request == SMFIR_INSHEADER) { rname = r->eom_rdata + MILTER_LEN_BYTES; rvalue = r->eom_rdata + MILTER_LEN_BYTES + strlen(rname) + 1; } else #endif /* SMFIR_INSHEADER */ { rname = r->eom_rdata; rvalue = r->eom_rdata + strlen(rname) + 1; } if (strcmp(name, rname) == 0 && rvalue != NULL) { if (idx == 0) { lua_pushstring(l, rvalue); return 1; } else { idx--; } } } } lua_pushnil(l); return 1; } /* ** USAGE -- print usage message ** ** Parameters: ** Not now. Maybe later. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\n" "\t-D name[=value]\tdefine global variable\n" "\t-s script \tscript to run (default = stdin)\n" "\t-u \treport usage statistics\n" "\t-v \tverbose mode\n" "\t-V \tprint version number and exit\n" "\t-w \tdon't wait for child at shutdown\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int c; int status; int fd; int retval = 0; ssize_t rlen; char *p; char *script = NULL; lua_State *l; struct mt_lua_io io; struct stat s; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; verbose = 0; filterpid = 0; tmo = DEFTIMEOUT; rusage = FALSE; nowait = FALSE; l = lua_newstate(mt_lua_alloc, NULL); if (l == NULL) { fprintf(stderr, "%s: unable to allocate new Lua state\n", progname); return 1; } luaL_openlibs(l); while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) { switch (c) { case 'D': p = strchr(optarg, '='); if (p != NULL) { *p = '\0'; lua_pushstring(l, p + 1); } else { lua_pushnumber(l, 1); } lua_setglobal(l, optarg); break; case 's': if (script != NULL) { fprintf(stderr, "%s: multiple use of '-%c' not permitted\n", progname, c); lua_close(l); return EX_USAGE; } script = optarg; break; case 'u': rusage = TRUE; break; case 'v': verbose++; break; case 'V': fprintf(stdout, "%s: %s v%s\n", progname, MT_PRODUCT, MT_VERSION); return 0; case 'w': nowait = TRUE; break; default: lua_close(l); return usage(); } } if (optind != argc) { lua_close(l); return usage(); } io.lua_io_done = FALSE; if (script != NULL) { fd = open(script, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: %s: open(): %s\n", progname, script, strerror(errno)); lua_close(l); return 1; } if (fstat(fd, &s) != 0) { fprintf(stderr, "%s: %s: fstat(): %s\n", progname, script, strerror(errno)); close(fd); lua_close(l); return 1; } io.lua_io_script = (const char *) malloc(s.st_size); if (io.lua_io_script == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); close(fd); lua_close(l); return 1; } rlen = read(fd, (void *) io.lua_io_script, s.st_size); if (rlen != s.st_size) { fprintf(stderr, "%s: %s: read() returned %zu (expecting %ld)\n", progname, script, rlen, (long) s.st_size); free((void *) io.lua_io_script); close(fd); lua_close(l); return 1; } io.lua_io_scriptlen = (size_t) s.st_size; close(fd); } else { io.lua_io_script = NULL; } /* register functions */ #if LUA_VERSION_NUM == 502 luaL_newlib(l, mt_library); lua_setglobal(l, "mt"); #else /* LUA_VERSION_NUM == 502 */ luaL_register(l, "mt", mt_library); #endif /* LUA_VERSION_NUM == 502 */ lua_pop(l, 1); /* register constants */ lua_pushnumber(l, MT_HDRINSERT); lua_setglobal(l, "MT_HDRINSERT"); lua_pushnumber(l, MT_HDRADD); lua_setglobal(l, "MT_HDRADD"); lua_pushnumber(l, MT_HDRCHANGE); lua_setglobal(l, "MT_HDRCHANGE"); lua_pushnumber(l, MT_HDRDELETE); lua_setglobal(l, "MT_HDRDELETE"); lua_pushnumber(l, MT_RCPTADD); lua_setglobal(l, "MT_RCPTADD"); lua_pushnumber(l, MT_RCPTDELETE); lua_setglobal(l, "MT_RCPTDELETE"); lua_pushnumber(l, MT_BODYCHANGE); lua_setglobal(l, "MT_BODYCHANGE"); lua_pushnumber(l, MT_QUARANTINE); lua_setglobal(l, "MT_QUARANTINE"); lua_pushnumber(l, MT_SMTPREPLY); lua_setglobal(l, "MT_SMTPREPLY"); lua_pushnumber(l, SMFIR_CONTINUE); lua_setglobal(l, "SMFIR_CONTINUE"); lua_pushnumber(l, SMFIR_ACCEPT); lua_setglobal(l, "SMFIR_ACCEPT"); lua_pushnumber(l, SMFIR_REJECT); lua_setglobal(l, "SMFIR_REJECT"); lua_pushnumber(l, SMFIR_TEMPFAIL); lua_setglobal(l, "SMFIR_TEMPFAIL"); lua_pushnumber(l, SMFIR_DISCARD); lua_setglobal(l, "SMFIR_DISCARD"); lua_pushnumber(l, SMFIR_REPLYCODE); lua_setglobal(l, "SMFIR_REPLYCODE"); #ifdef SMFIR_SKIP lua_pushnumber(l, SMFIR_SKIP); lua_setglobal(l, "SMFIR_SKIP"); #endif /* SMFIR_SKIP */ lua_pushnumber(l, SMFIC_CONNECT); lua_setglobal(l, "SMFIC_CONNECT"); lua_pushnumber(l, SMFIC_HELO); lua_setglobal(l, "SMFIC_HELO"); lua_pushnumber(l, SMFIC_MAIL); lua_setglobal(l, "SMFIC_MAIL"); lua_pushnumber(l, SMFIC_RCPT); lua_setglobal(l, "SMFIC_RCPT"); lua_pushnumber(l, SMFIP_NOCONNECT); lua_setglobal(l, "SMFIP_NOCONNECT"); lua_pushnumber(l, SMFIP_NOHELO); lua_setglobal(l, "SMFIP_NOHELO"); lua_pushnumber(l, SMFIP_NOMAIL); lua_setglobal(l, "SMFIP_NOMAIL"); lua_pushnumber(l, SMFIP_NORCPT); lua_setglobal(l, "SMFIP_NORCPT"); lua_pushnumber(l, SMFIP_NOBODY); lua_setglobal(l, "SMFIP_NOBODY"); lua_pushnumber(l, SMFIP_NOHDRS); lua_setglobal(l, "SMFIP_NOHDRS"); lua_pushnumber(l, SMFIP_NOEOH); lua_setglobal(l, "SMFIP_NOEOH"); #ifdef SMFIP_NR_HDR lua_pushnumber(l, SMFIP_NR_HDR); lua_setglobal(l, "SMFIP_NR_HDR"); #endif /* SMFIP_NR_HDR */ #ifdef SMFIP_NOHREPL lua_pushnumber(l, SMFIP_NOHREPL); lua_setglobal(l, "SMFIP_NOHREPL"); #endif /* SMFIP_NOHREPL */ #ifdef SMFIP_NOUNKNOWN lua_pushnumber(l, SMFIP_NOUNKNOWN); lua_setglobal(l, "SMFIP_NOUNKNOWN"); #endif /* SMFIP_NOUNKNOWN */ #ifdef SMFIP_NODATA lua_pushnumber(l, SMFIP_NODATA); lua_setglobal(l, "SMFIP_NODATA"); #endif /* SMFIP_NODATA */ #ifdef SMFIP_SKIP lua_pushnumber(l, SMFIP_SKIP); lua_setglobal(l, "SMFIP_SKIP"); #endif /* SMFIP_SKIP */ #ifdef SMFIP_RCPT_REJ lua_pushnumber(l, SMFIP_RCPT_REJ); lua_setglobal(l, "SMFIP_RCPT_REJ"); #endif /* SMFIP_RCPT_REJ */ lua_pushnumber(l, SMFIP_NR_CONN); lua_setglobal(l, "SMFIP_NR_CONN"); lua_pushnumber(l, SMFIP_NR_HELO); lua_setglobal(l, "SMFIP_NR_HELO"); lua_pushnumber(l, SMFIP_NR_MAIL); lua_setglobal(l, "SMFIP_NR_MAIL"); lua_pushnumber(l, SMFIP_NR_RCPT); lua_setglobal(l, "SMFIP_NR_RCPT"); lua_pushnumber(l, SMFIP_NR_DATA); lua_setglobal(l, "SMFIP_NR_DATA"); lua_pushnumber(l, SMFIP_NR_UNKN); lua_setglobal(l, "SMFIP_NR_UNKN"); lua_pushnumber(l, SMFIP_NR_EOH); lua_setglobal(l, "SMFIP_NR_EOH"); lua_pushnumber(l, SMFIP_NR_BODY); lua_setglobal(l, "SMFIP_NR_BODY"); #ifdef SMFIP_HDR_LEADSPC lua_pushnumber(l, SMFIP_HDR_LEADSPC); lua_setglobal(l, "SMFIP_HDR_LEADSPC"); #endif /* SMFIP_HDR_LEADSPC */ #ifdef SMFIP_MDS_256K lua_pushnumber(l, SMFIP_MDS_256K); lua_setglobal(l, "SMFIP_MDS_256K"); #endif /* SMFIP_MDS_256K */ #ifdef SMFIP_MDS_1M lua_pushnumber(l, SMFIP_MDS_1M); lua_setglobal(l, "SMFIP_MDS_1M"); #endif /* SMFIP_MDS_1M */ #ifdef SMFIP_TEST lua_pushnumber(l, SMFIP_TEST); lua_setglobal(l, "SMFIP_TEST"); #endif /* SMFIP_TEST */ lua_pushnumber(l, SMFIF_ADDHDRS); lua_setglobal(l, "SMFIF_ADDHDRS"); lua_pushnumber(l, SMFIF_CHGBODY); lua_setglobal(l, "SMFIF_CHGBODY"); lua_pushnumber(l, SMFIF_MODBODY); lua_setglobal(l, "SMFIF_MODBODY"); lua_pushnumber(l, SMFIF_ADDRCPT); lua_setglobal(l, "SMFIF_ADDRCPT"); lua_pushnumber(l, SMFIF_DELRCPT); lua_setglobal(l, "SMFIF_DELRCPT"); lua_pushnumber(l, SMFIF_CHGHDRS); lua_setglobal(l, "SMFIF_CHGHDRS"); #ifdef SMFIF_QUARANTINE lua_pushnumber(l, SMFIF_QUARANTINE); lua_setglobal(l, "SMFIF_QUARANTINE"); #endif /* SMFIF_QUARANTINE */ #ifdef SMFIF_CHGFROM lua_pushnumber(l, SMFIF_CHGFROM); lua_setglobal(l, "SMFIF_CHGFROM"); #endif /* SMFIF_CHGFROM */ #ifdef SMFIF_ADDRCPT_PAR lua_pushnumber(l, SMFIF_ADDRCPT_PAR); lua_setglobal(l, "SMFIF_ADDRCPT_PAR"); #endif /* SMFIF_ADDRCPT_PAR */ #ifdef SMFIF_SETSYMLIST lua_pushnumber(l, SMFIF_SETSYMLIST); lua_setglobal(l, "SMFIF_SETSYMLIST"); #endif /* SMFIF_SETSYMLIST */ #if LUA_VERSION_NUM == 502 switch (lua_load(l, mt_lua_reader, (void *) &io, script == NULL ? "(stdin)" : script, NULL)) #else /* LUA_VERSION_NUM == 502 */ switch (lua_load(l, mt_lua_reader, (void *) &io, script == NULL ? "(stdin)" : script)) #endif /* LUA_VERSION_NUM == 502 */ { case 0: break; case LUA_ERRSYNTAX: case LUA_ERRMEM: if (lua_isstring(l, 1)) { fprintf(stderr, "%s: %s: %s\n", progname, script == NULL ? "(stdin)" : script, lua_tostring(l, 1)); } lua_close(l); if (io.lua_io_script != NULL) free((void *) io.lua_io_script); return 1; default: assert(0); } (void) srandom(time(NULL)); status = lua_pcall(l, 0, LUA_MULTRET, 0); if (lua_gettop(l) == 1 && lua_isstring(l, 1)) { fprintf(stderr, "%s: %s: %s\n", progname, script == NULL ? "(stdin)" : script, lua_tostring(l, 1)); } if (rusage) { struct rusage u; if (getrusage(RUSAGE_SELF, &u) != 0) { fprintf(stderr, "%s: getrusage(RUSAGE_SELF): %s\n", progname, strerror(errno)); retval = 2; } fprintf(stdout, "%s: self: user %u.%06u, system %u.%06u\n", progname, (unsigned) u.ru_utime.tv_sec, (unsigned) u.ru_utime.tv_usec, (unsigned) u.ru_stime.tv_sec, (unsigned) u.ru_stime.tv_usec); } if (status != 0) retval = 1; lua_close(l); if (io.lua_io_script != NULL) free((void *) io.lua_io_script); if (filterpid != 0) { if (kill(filterpid, SIGTERM) != 0) { fprintf(stderr, "%s: %d: kill() %s\n", progname, filterpid, strerror(errno)); } else if (!nowait) { if (verbose > 1) { fprintf(stdout, "%s: waiting for process %d\n", progname, filterpid); } (void) wait(&status); if (WIFEXITED(status) && WEXITSTATUS(status) != 0) { fprintf(stderr, "%s: filter process exited with status %d\n", progname, WEXITSTATUS(status)); retval = 1; } else if (WIFSIGNALED(status) && WTERMSIG(status) != SIGTERM) { fprintf(stderr, "%s: filter process died with signal %d\n", progname, WTERMSIG(status)); retval = 1; } } } if (rusage && !nowait) { struct rusage u; if (getrusage(RUSAGE_CHILDREN, &u) != 0) { fprintf(stderr, "%s: getrusage(RUSAGE_CHILDREN): %s\n", progname, strerror(errno)); retval = 2; } fprintf(stdout, "%s: child: user %u.%06u, system %u.%06u\n", progname, (unsigned) u.ru_utime.tv_sec, (unsigned) u.ru_utime.tv_usec, (unsigned) u.ru_stime.tv_sec, (unsigned) u.ru_stime.tv_usec); } return retval; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/000077500000000000000000000000001337314105200202635ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/.gitignore000066400000000000000000000011511337314105200222510ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno opendkim*.[58] t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure configure.scan aclocal.m4 depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile .deps opendkim-testadsp opendkim opendkim-stats opendkim-testmsg opendkim-testkey opendkim-genzone opendkim-genkey .libs core *.core opendkim-lua.3 opendkim.conf.simple-verify opendkim.conf.simple opendkim-atpszone opendkim-atpszone.8 opendkim-spam opendkim-spam.1 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/Makefile.am000066400000000000000000000245121337314105200223230ustar00rootroot00000000000000# Copyright (c) 2010-2014, The Trusted Domain Project. All rights reserved. # if DEBUG AM_CFLAGS = -g endif sbin_PROGRAMS = opendkim-genzone opendkim-testkey opendkim-testmsg if ATPS sbin_PROGRAMS += opendkim-atpszone endif if STATS if USE_ODBX bin_PROGRAMS = opendkim-spam endif sbin_PROGRAMS += opendkim-stats endif dist_sbin_SCRIPTS = opendkim-genkey dist_doc_DATA = opendkim.conf.sample opendkim.conf.simple \ opendkim.conf.simple-verify README.SQL if BUILD_FILTER sbin_PROGRAMS += opendkim opendkim_SOURCES = opendkim.c opendkim.h opendkim-ar.c opendkim-ar.h opendkim-arf.c opendkim-arf.h opendkim-config.h opendkim-crypto.c opendkim-crypto.h opendkim-db.c opendkim-db.h opendkim-dns.c opendkim-dns.h opendkim-lua.c opendkim-lua.h config.c config.h flowrate.c flowrate.h reputation.c reputation.h stats.c stats.h test.c test.h util.c util.h opendkim_CC = $(PTHREAD_CC) opendkim_CFLAGS = $(PTHREAD_CFLAGS) $(LIBCRYPTO_CFLAGS) $(COV_CFLAGS) opendkim_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBCRYPTO_CPPFLAGS) opendkim_LDFLAGS = $(LIBCRYPTO_LIBDIRS) $(LIBMILTER_LIBDIRS) $(PTHREAD_CFLAGS) $(COV_LDFLAGS) opendkim_LDADD = ../libopendkim/libopendkim.la $(LIBMILTER_LIBS) $(LIBCRYPTO_LIBS) $(PTHREAD_LIBS) $(COV_LIBADD) $(LIBRESOLV) if USE_DB_OPENDKIM opendkim_CPPFLAGS += $(LIBDB_INCDIRS) opendkim_LDFLAGS += $(LIBDB_LIBDIRS) opendkim_LDADD += $(LIBDB_LIBS) endif if USE_ODBX opendkim_CPPFLAGS += $(LIBODBX_CPPFLAGS) opendkim_LDFLAGS += $(LIBODBX_LDFLAGS) opendkim_CFLAGS += $(LIBODBX_CFLAGS) opendkim_LDADD += $(LIBODBX_LIBS) $(LIBDL_LIBS) endif if USE_LIBMEMCACHED opendkim_CPPFLAGS += $(LIBMEMCACHED_INCDIRS) opendkim_LDFLAGS += $(LIBMEMCACHED_LIBDIRS) opendkim_LDADD += $(LIBMEMCACHED_LIBS) endif if LUA SUBDIRS=tests opendkim_CPPFLAGS += $(LIBLUA_INCDIRS) -DDKIMF_LUA_CONTEXT_HOOKS opendkim_LDFLAGS += $(LIBLUA_LIBDIRS) opendkim_LDADD += $(LIBLUA_LIBS) endif if USE_SASL opendkim_CPPFLAGS += $(SASL_CPPFLAGS) endif if USE_LDAP opendkim_CPPFLAGS += $(OPENLDAP_CPPFLAGS) opendkim_LDADD += $(OPENLDAP_LIBS) endif if USE_UNBOUND opendkim_CPPFLAGS += $(LIBUNBOUND_INCDIRS) opendkim_LDFLAGS += $(LIBUNBOUND_LIBDIRS) $(LIBLDNS_LIBDIRS) $(LIBEVENT_LIBDIRS) opendkim_LDADD += $(LIBUNBOUND_LIBS) $(LIBLDNS_LIBS) $(LIBEVENT_LIBS) endif if VBR opendkim_CPPFLAGS += -I$(srcdir)/../libvbr opendkim_LDADD += ../libvbr/libvbr.la endif if RBL opendkim_CPPFLAGS += -I$(srcdir)/../librbl opendkim_LDADD += ../librbl/librbl.la endif if REPUTE opendkim_CPPFLAGS += -I$(srcdir)/../reputation opendkim_LDADD += ../reputation/librepute.la endif if USE_MDB opendkim_CPPFLAGS += $(LIBMDB_CPPFLAGS) opendkim_LDADD += $(LIBMDB_LIBS) endif if ERLANG opendkim_CPPFLAGS += $(LIBERL_INCDIRS) opendkim_LDFLAGS += $(LIBERL_LIBDIRS) opendkim_LDADD += $(LIBERL_LIBS) endif if REPRRD opendkim_CPPFLAGS += -I$(srcdir)/../reprrd opendkim_LDADD += ../reprrd/libreprrd.la endif opendkim_CPPFLAGS += $(LIBMILTER_INCDIRS) endif if STATS opendkim_stats_CC = $(PTHREAD_CC) opendkim_stats_SOURCES = opendkim-stats.c opendkim_stats_CPPFLAGS = -I$(srcdir)/../libopendkim opendkim_stats_LDFLAGS = $(COV_LDFLAGS) opendkim_stats_LDADD = ../libopendkim/libopendkim.la $(LIBCRYPTO_LIBS) $(COV_LIBADD) $(PTHREAD_LIBS) opendkim_stats_CFLAGS = $(LIBCRYPTO_CFLAGS) $(COV_CFLAGS) $(PTHREAD_CFLAGS) opendkim_stats_CFLAGS += $(PTHREAD_CFLAGS) endif opendkim_testkey_CC = $(PTHREAD_CC) opendkim_testkey_SOURCES = config.c config.h opendkim-crypto.c opendkim-crypto.h opendkim-db.c opendkim-db.h opendkim-dns.c opendkim-dns.h opendkim-lua.c opendkim-lua.h opendkim-testkey.c util.c util.h $(srcdir)/../libopendkim/dkim.h $(srcdir)/../libopendkim/dkim-test.h opendkim_testkey_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBCRYPTO_CPPFLAGS) opendkim_testkey_CFLAGS = $(LIBCRYPTO_CFLAGS) $(COV_CFLAGS) $(PTHREAD_CFLAGS) opendkim_testkey_LDFLAGS = $(LIBCRYPTO_LIBDIRS) $(COV_LDFLAGS) $(PTHREAD_CFLAGS) opendkim_testkey_LDADD = ../libopendkim/libopendkim.la $(LIBCRYPTO_LIBS) $(LIBRESOLV) $(COV_LIBADD) $(PTHREAD_LIBS) if LUA opendkim_testkey_CPPFLAGS += $(LIBLUA_INCDIRS) $(LIBMILTER_INCDIRS) opendkim_testkey_LDFLAGS += $(LIBLUA_LIBDIRS) opendkim_testkey_LDADD += $(LIBLUA_LIBS) endif if USE_DB_OPENDKIM opendkim_testkey_CPPFLAGS += $(LIBDB_INCDIRS) opendkim_testkey_LDFLAGS += $(LIBDB_LIBDIRS) opendkim_testkey_LDADD += $(LIBDB_LIBS) endif if USE_ODBX opendkim_testkey_CPPFLAGS += $(LIBODBX_CPPFLAGS) opendkim_testkey_LDFLAGS += $(LIBODBX_LDFLAGS) opendkim_testkey_CFLAGS += $(LIBODBX_CFLAGS) opendkim_testkey_LDADD += $(LIBODBX_LIBS) $(LIBDL_LIBS) endif if USE_LIBMEMCACHED opendkim_testkey_CPPFLAGS += $(LIBMEMCACHED_INCDIRS) opendkim_testkey_LDFLAGS += $(LIBMEMCACHED_LIBDIRS) opendkim_testkey_LDADD += $(LIBMEMCACHED_LIBS) endif if USE_LDAP opendkim_testkey_CPPFLAGS += $(OPENLDAP_CPPFLAGS) opendkim_testkey_LDADD += $(OPENLDAP_LIBS) endif if USE_SASL opendkim_testkey_CPPFLAGS += $(SASL_CPPFLAGS) endif if USE_UNBOUND opendkim_testkey_CPPFLAGS += $(LIBUNBOUND_INCDIRS) opendkim_testkey_LDFLAGS += $(LIBUNBOUND_LIBDIRS) $(LIBLDNS_LIBDIRS) opendkim_testkey_LDADD += $(LIBUNBOUND_LIBS) $(LIBLDNS_LIBS) endif if RBL opendkim_testkey_CPPFLAGS += -I$(srcdir)/../librbl opendkim_testkey_LDADD += ../librbl/librbl.la endif if VBR opendkim_testkey_CPPFLAGS += -I$(srcdir)/../libvbr opendkim_testkey_LDADD += ../libvbr/libvbr.la endif if REPUTE opendkim_testkey_CPPFLAGS += -I$(srcdir)/../reputation opendkim_testkey_LDADD += ../reputation/librepute.la endif if USE_MDB opendkim_testkey_CPPFLAGS += $(LIBMDB_CPPFLAGS) opendkim_testkey_CFLAGS += $(LIBMDB_CFLAGS) opendkim_testkey_LDADD += $(LIBMDB_LIBS) endif if ERLANG opendkim_testkey_CPPFLAGS += $(LIBERL_INCDIRS) opendkim_testkey_LDFLAGS += $(LIBERL_LIBDIRS) opendkim_testkey_LDADD += $(LIBERL_LIBS) endif opendkim_testmsg_CC = $(PTHREAD_CC) opendkim_testmsg_SOURCES = opendkim-testmsg.c opendkim_testmsg_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBCRYPTO_CPPFLAGS) opendkim_testmsg_CFLAGS = $(LIBCRYPTO_CFLAGS) $(COV_CFLAGS) $(PTHREAD_CFLAGS) opendkim_testmsg_LDFLAGS = $(COV_LDFLAGS) $(PTHREAD_CFLAGS) opendkim_testmsg_LDADD = ../libopendkim/libopendkim.la $(LIBCRYPTO_LIBS) $(LIBRESOLV) $(COV_LIBADD) $(PTHREAD_LIBS) opendkim_genzone_CC = $(PTHREAD_CC) opendkim_genzone_SOURCES = config.c config.h opendkim-db.c opendkim-db.h opendkim-genzone.c opendkim-lua.c util.c util.h opendkim_genzone_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBCRYPTO_CPPFLAGS) opendkim_genzone_CFLAGS = $(PTHREAD_CFLAGS) $(LIBCRYPTO_CFLAGS) $(COV_CFLAGS) opendkim_genzone_LDFLAGS = $(COV_LDFLAGS) $(LIBCRYPTO_LIBDIRS) $(PTHREAD_CFLAGS) opendkim_genzone_LDADD = ../libopendkim/libopendkim.la $(LIBCRYPTO_LIBS) $(COV_LIBADD) $(PTHREAD_LIBS) if USE_DB_OPENDKIM opendkim_genzone_CPPFLAGS += $(LIBDB_INCDIRS) opendkim_genzone_LDFLAGS += $(LIBDB_LIBDIRS) opendkim_genzone_LDADD += $(LIBDB_LIBS) endif if USE_ODBX opendkim_genzone_CPPFLAGS += $(LIBODBX_CPPFLAGS) opendkim_genzone_LDFLAGS += $(LIBODBX_LDFLAGS) opendkim_genzone_CFLAGS += $(LIBODBX_CFLAGS) opendkim_genzone_LDADD += $(LIBODBX_LIBS) $(LIBDL_LIBS) endif if USE_LIBMEMCACHED opendkim_genzone_CPPFLAGS += $(LIBMEMCACHED_INCDIRS) opendkim_genzone_LDFLAGS += $(LIBMEMCACHED_LIBDIRS) opendkim_genzone_LDADD += $(LIBMEMCACHED_LIBS) endif if USE_SASL opendkim_genzone_CPPFLAGS += $(SASL_CPPFLAGS) endif if USE_LDAP opendkim_genzone_CPPFLAGS += $(OPENLDAP_CPPFLAGS) opendkim_genzone_LDADD += $(OPENLDAP_LIBS) endif if LUA opendkim_genzone_CPPFLAGS += $(LIBLUA_INCDIRS) $(LIBMILTER_INCDIRS) opendkim_genzone_LDFLAGS += $(LIBLUA_LIBDIRS) opendkim_genzone_LDADD += $(LIBLUA_LIBS) endif if REPUTE opendkim_genzone_CPPFLAGS += -I$(srcdir)/../reputation opendkim_genzone_LDADD += ../reputation/librepute.la endif if USE_MDB opendkim_genzone_CPPFLAGS += $(LIBMDB_CPPFLAGS) opendkim_genzone_CFLAGS += $(LIBMDB_CFLAGS) opendkim_genzone_LDADD += $(LIBMDB_LIBS) endif if ERLANG opendkim_genzone_CPPFLAGS += $(LIBERL_INCDIRS) opendkim_genzone_LDFLAGS += $(LIBERL_LIBDIRS) opendkim_genzone_LDADD += $(LIBERL_LIBS) endif if ATPS opendkim_atpszone_CC = $(PTHREAD_CC) opendkim_atpszone_SOURCES = config.c config.h opendkim-db.c opendkim-db.h opendkim-atpszone.c opendkim-lua.c util.c util.h opendkim_atpszone_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBCRYPTO_CPPFLAGS) opendkim_atpszone_CFLAGS = $(COV_CFLAGS) $(LIBCRYPTO_CFLAGS) $(PTHREAD_CFLAGS) opendkim_atpszone_LDFLAGS = $(COV_LDFLAGS) $(LIBCRYPTO_LIBDIRS) $(PTHREAD_CFLAGS) opendkim_atpszone_LDADD = ../libopendkim/libopendkim.la $(COV_LIBADD) $(LIBCRYPTO_LIBS) $(PTHREAD_LIBS) if USE_DB_OPENDKIM opendkim_atpszone_CPPFLAGS += $(LIBDB_INCDIRS) opendkim_atpszone_LDFLAGS += $(LIBDB_LIBDIRS) opendkim_atpszone_LDADD += $(LIBDB_LIBS) endif if USE_ODBX opendkim_atpszone_CPPFLAGS += $(LIBODBX_CPPFLAGS) opendkim_atpszone_LDFLAGS += $(LIBODBX_LDFLAGS) opendkim_atpszone_CFLAGS += $(LIBODBX_CFLAGS) opendkim_atpszone_LDADD += $(LIBODBX_LIBS) $(LIBDL_LIBS) endif if USE_LIBMEMCACHED opendkim_atpszone_CPPFLAGS += $(LIBMEMCACHED_INCDIRS) opendkim_atpszone_LDFLAGS += $(LIBMEMCACHED_LIBDIRS) opendkim_atpszone_LDADD += $(LIBMEMCACHED_LIBS) endif if USE_SASL opendkim_atpszone_CPPFLAGS += $(SASL_CPPFLAGS) endif if USE_LDAP opendkim_atpszone_CPPFLAGS += $(OPENLDAP_CPPFLAGS) opendkim_atpszone_LDADD += $(OPENLDAP_LIBS) endif if LUA opendkim_atpszone_CPPFLAGS += $(LIBLUA_INCDIRS) $(LIBMILTER_INCDIRS) opendkim_atpszone_LDFLAGS += $(LIBLUA_LIBDIRS) opendkim_atpszone_LDADD += $(LIBLUA_LIBS) endif if REPUTE opendkim_atpszone_CPPFLAGS += -I$(srcdir)/../reputation opendkim_atpszone_LDADD += ../reputation/librepute.la endif if USE_MDB opendkim_atpszone_CPPFLAGS += $(LIBMDB_CPPFLAGS) opendkim_atpszone_CFLAGS += $(LIBMDB_CFLAGS) opendkim_atpszone_LDADD += $(LIBMDB_LIBS) endif if ERLANG opendkim_atpszone_CPPFLAGS += $(LIBERL_INCDIRS) opendkim_atpszone_LDFLAGS += $(LIBERL_LIBDIRS) opendkim_atpszone_LDADD += $(LIBERL_LIBS) endif endif if STATS if USE_ODBX opendkim_spam_SOURCES = config.c config.h opendkim-spam.c opendkim_spam_CPPFLAGS = -I$(srcdir)/../libopendkim $(LIBODBX_CPPFLAGS) opendkim_spam_CFLAGS = $(COV_CFLAGS) $(LIBODBX_CFLAGS) opendkim_spam_LDFLAGS = $(COV_LDFLAGS) $(LIBODBX_LDFLAGS) opendkim_spam_LDADD = $(COV_LIBADD) $(LIBODBX_LIBS) $(LIBDL_LIBS) endif endif if LUA dist_doc_DATA += \ setup.lua.sample \ screen.lua.sample \ final.lua.sample endif man_MANS = opendkim-genkey.8 opendkim-genzone.8 opendkim-testkey.8 \ opendkim-testmsg.8 if BUILD_FILTER man_MANS += opendkim.conf.5 opendkim.8 if LUA man_MANS += opendkim-lua.3 endif endif if STATS man_MANS += opendkim-stats.8 endif if ATPS man_MANS += opendkim-atpszone.8 endif if STATS if USE_ODBX man_MANS += opendkim-spam.1 endif endif OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/README000066400000000000000000001022611337314105200211450ustar00rootroot00000000000000 INTRODUCTION ============ This document will walk you through the process of configuring and activating the OpenDKIM filter once it has been compiled and installed. In doing so you will: o Generate a private and public key pair for use when signing your mail (skipped if you will only be verifying) o Post your public key in your DNS space (also skipped if only verifying) o Choose a local socket interface between the filter and your MTA o Configure your filter o Activate your filter o Test your filter COMPILING AND INSTALLING ======================== The INSTALL document in the root of the build directory covers the compilation and software installation of opendkim and its prerequisites. You should complete that process before continuing with the next section. SOCKET SELECTION ================ Your MTA and your opendkim filter will communicate over a socket connection. You can choose to use a TCP (network) socket or a UNIX domain (filesystem) socket. They each have advantages: A UNIX domain socket can be secured using the filesystem (i.e., with user or group permissions), but cannot be reached from other machines that might want to share the service. For a UNIX domain socket, you must pick a location within your filesystem that the opendkim filter will be able to access in which the socket will be created for MTAs to connect, and set file permissions accordingly. For a TCP socket, you must select a port number not in use by other applications, and the name or IP address of the interface on which opendkim should listen for connections. The IP address can be simply "ANY" if all connections should be accepted. You will also need to ensure that any packet filters in effect on the local machine permit traffic to and from that port, and that any other kernel-level policy mechanisms (e.g., selinux) will permit traffic on that port. For selinux, the following command will need to be executed as the superuser, which declares the chosen port to be a milter application port: semanage port -a -t milter_port_t -p tcp Consult your documentation for other packet filter and policy systems. CONFIGURING OPENDKIM ==================== NOTE: If you will only be verfiying incoming mail and will not be signing, start at step (5). (1) Choose a selector name. A selector is simply a symbolic name given to a key you will be using to sign your mail. You are free to choose any name you wish. One current convention if you are using multiple mailservers is to use the hostname (hostname only, not the fully-qualified domain name) of the host that will be providing the service. Another convention is to use the current month and year. (2) Run the script "opendkim-genkey -s SELECTOR". The opendkim-genkey man page has full details of options. This will generate a private key in PEM format and output a TXT record containing the matching public key appropriate for insertion into your DNS zone file. Insert it in your zone file, increment the serial number, and reload your DNS system so the data is published. (3) Publish your public DNS key. The public key DNS record should appear as a TXT resource record at: SELECTOR._domainkey.DOMAIN SELECTOR is the name you chose in step (1) above and will use with the Selector config option or the result of the KeyTable lookup. DOMAIN is the domain name specified in the "-d" command line, the Domain option in the configuration file, or the domain that would be returned from a KeyTable lookup. For a translation of the parameters and value pairs, see RFC6376. Using "t=y" is indicates you are in "test mode", advising verifiers that they should not take any real action based on success or failure of the use of this key after verifing a message. Remove the "t=y" once you have tested the DKIM signing of your messages to your satisfaction. You might want to set a short TTL on this record during testing so changes are propagated to other nameservers more quickly. Reload your nameserver so that the record gets published. If you are running BIND 9 the command is "rndc reload"; for other nameservers, consult your vendor documentation. Check that the DNS server is returning your published DNS record. Be aware that synchronization to secondary DNS servers and negative caching of DNS resolver servers may effect the results observed. For reliable results, query your DNS server directly: dig -t txt SELECTOR._domainkey.DOMAIN NAMESERVER NAMESERVER is a nameserver for your domain. You can get a list of these using: dig -t ns DOMAIN If the key can be retreived correctly then opendkim-testkey can be used to verify that the key matches the private key. opendkim-testkey -d DOMAIN -s SELECTOR -k rsa.private BIND servers have a 256 byte limit on serving TXT records, so a 1024 bit RSA key is recommended if using BIND as your primary DNS server. See section on LARGE KEYS. (4) Store the private key in a safe place. We generally use a path like /var/db/dkim/SELECTOR.key.pem (where "SELECTOR" is the name you chose). The /var/db/dkim directory and the associated .pem file should be owned by the user that will be executing the filter (preferably not the superuser) and be mode 0700 and 0600 respectively. (5) Take a look at the opendkim.conf.simple as an example configuration file for your domain. If you wish to sign mail that comes from sources other than the localhost address (127.0.0.1), include these in CIDR notation in the confiugration file for the InternalHosts configuration option. (6) Start opendkim. You will need at least the "-p" option. The current recommended set of command line options is: -l -p SOCKETSPEC -d DOMAIN -k KEYPATH -s SELECTOR ...where SOCKETSPEC is the socket you told your MTA to use, DOMAIN is the domain or set of domains for which you want to sign mail, KEYPATH is the path to the private key file you generated, and SELECTOR is the selector name you picked. You can tack "-f" on there if you want it to run in the foreground instead of in the background as a daemon. Instead of command line options, you can also use a configuration file. In that case, you only need to tell the filter where the configuration file is by specifying a command line option of: -x CONFPATH ...where CONFPATH is the path to the configuration file you wish to use. One or more configuration example files are provided. (7) Configure your MTA: For Sendmail: (a) Choose a socket at which the MTA and the filter will rendezvous (see the documentation in libmilter for details) (b) Add a line like this example to your sendmail.mc using your desired socket specification: INPUT_MAIL_FILTER(`opendkim', `S=inet:8891@localhost') (c) Rebuild your sendmail.cf in the usual way For Postfix: (a) Choose a socket at which the MTA and the filter will rendezvous. Be careful with UNIX domain sockets as on some distributions and setups the smtpd process is running in a chroot environment. A UNIX socket will need to be visible to the chrooted smtpd process. (b) Add the following lines like this example to your postfix main.cf using your desired socket specification: smtpd_milters = inet:localhost:8891 non_smtpd_milters = inet:localhost:8891 (c) If you have a content filter in master.cf that feeds it back into a different smtpd process, you should alter the second smtpd process in master.cf to contain '-o receive_override_options=no_milters' to prevent messages being signed or verified twice. For tips on avoiding DKIM signature breakage, see: http://www.postfix.org/MILTER_README.html#workarounds (8) Restart/reload your MTA. For Sendmail: kill -1 `head -1 /var/run/sendmail.pid` For Postfix: postfix reload ...or the following if master.cf was changed: /etc/init.d/postfix restart ISSUES USING SENDMAIL TO SIGN AND VERIFY ======================================== When using the sendmail MTA in both signing and verifying mode, there are a few issues of which to be aware that might cause operational problems and deserve consideration. (a) When the MTA will be used for relaying emails, e.g. delivering to other hosts using the aliases mechanism, it is important not to break signatures inserted by the original sender. This is particularly sensitive particular when the sending domain has published a "reject" DMARC policy. By default, sendmail quotes to address header fields when there are no quotes and the display part of the address contains a period or an apostrophe. However, opendkim only sees the raw, unmodified form of the header field, and so the content that gets verified and what gets signed will not be the same, guaranteeing the attached signature is not valid. To direct sendmail not to modify the headers, add this to your sendmail.mc: conf(`confMUST_QUOTE_CHARS', `') (b) As stated in sendmail's KNOWNBUGS file, sendmail truncates header field values longer than 256 characters, which could mean truncating the domain of a long From: header field value and invalidating the signature. You may wish to consider increasing MAXNAME in sendmail/conf.h to mitigate changing the messages and invalidating their signatures. This change requires recompiling sendmail. (c) Similar to (a) above, sendmail may wrap very long single-line recipient fields for presentation purposes; for example: To: very long name ,anotherloo...ong name b ...might be rewritten as: To: very long name , anotherloo...ong name b This rewrite is also done after opendkim has seen the message, meaning the signature opendkim attaches to the message does not match the content it signed. There is not a known configuration change to mitigate this mutation. The only known mechanism for dealing with this is to have distinct instances of opendkim do the verifying (inbound) and signing (outbound) so that the version that arrives at the signing instance is already in the rewritten form, guaranteeing the input and output are the same and thus the signature matches the payload. COMPLEX SIGNING CONFIGURATIONS ============================== The KeyTable and SigningTable are used to define signing instructions to the filter where use of Domain, Selector and KeyFile together are insufficient. First, select the type of database you will use for each. They need not be the same. The "DATA SETS" portion of the opendkim(8) man page describes the possibilities and how they are formatted. Then, construct those databases. Let's suppose you want to sign for two domains, example.com and example.net. Within example.com, you want to sign for user "president" differently than everyone else. Let's say further that you want to use a flat text file. You've generated private key files for each of these and stored them in the directory /usr/local/etc/dkim/keys as files "president", "excom" and "exnet", with the obvious intents. You want to use selectors "foo", "bar" and "baz" for those, respectively. The signing domains match the senders (i.e. the signatures for example.com's stuff will be held by example.com, and example.net likewise). First, write the KeyTable. This is a list of the keys you intend to use, and you just assign arbitrary names to them. So as a flat file, the KeyTable for the above might look like this: preskey example.com:foo:/usr/local/etc/dkim/keys/president comkey example.com:bar:/usr/local/etc/dkim/keys/excom netkey example.net:baz:/usr/local/etc/dkim/keys/exnet Per the documentation, multi-field data sets that are made of flat files have the fields separated by colons, but the key and value(s) are separated by whitespace. So now we've named each key file, and specified with which selector and domain each will be used, and then given each of those groupings a name. This is your KeyTable. Let's say you put it in /usr/local/etc/dkim/keytable. Next, write the SigningTable. This maps senders (by default, taken from the From: header field of a message passing through the filter) to which keys will be used to sign their mail. Wildcards are allowed. So to do what was described above, we write it as follows: president@example.com preskey *@example.com comkey *@example.net netkey Since we want to use wildcards, we can't actually use a regular flat file. Wildcards require a regular expression file, or "refile". The above is valid format for one of those. Let's say you put this in /usr/local/etc/dkim/signingtable. Finally, tell the filter that it should use these files by adding this to your configuration file: KeyTable /usr/local/etc/dkim/keytable SigningTable refile:/usr/local/etc/dkim/signingtable You could put "file:" in front of the filename for the KeyTable just to be precise, but "file:" is assumed if the value starts with a "/". HANDLING 8-BIT MESSAGES (sendmail) =================================== SMTP was not designed for handling of other than 7-bit ASCII, and the mechanisms to do so were added later. There is considerable flexibility in how this is done, and as a result each agent does it slightly differently. Because of this disparity, OpenDKIM can't reliably sign 8-bit data because it will be downgraded in an unpredictable way somewhere after signing, rendering the signature invalid. Instead, the MTA that will handle the 8-bit message has to downgrade it before presenting it for signing. To do this with sendmail, for example, add this to your sendmail.mc file: define(`confSEVEN_BIT_INPUT',true)dnl NOTES ON POSTFIX REWRITING OF MESSAGES ====================================== Like other MIME-aware MTAs, Postfix downgrades 8bit body content to 7bit when a remote SMTP server does not announce 8BITMIME support. If DKIM signatures must survive transmission to servers that don't announce 8BITMIME, it is recommented to downgrade before signing (for example, specify "-o smtp_discard_ehlo_keywords=8bitmime,silent-discard" for an SMTP client that delivers to a null filter or to amavisd). It's possible to specify "disable_mime_output_conversion = no" locally, but that won't prevent remote MTAs from doing the 8bit to 7bit downgrade and breaking DKIM signatures. It's also possible to prevent Postfix from adding From/Date/Message-ID header field, and from rewriting addresses in headers, by setting the "-G" flag for the sendmail command, and by setting "local_header_rewrite_clients" to empty. (By default, these modifications are enabled only for submissions by local processes and from clients in local networks.) Otherwise, Postfix should not modify a well-formed email message. For example, if the address in a From/To/etc. header field is not modified, then the field is passed through unchanged regardless of the content of mailbox display names, comments, etc. However, there are no guarantees for out-of-spec email and for some obsolete forms. For example, Postfix will fold lines over 998 characters long (not including the ) by inserting to minimize damage to MIME-formatted messages, will truncate (multiline) headers that contain more than 102400 bytes or more than 10240 tokens, and will replace the obsolete form "headername :" with the normal form "headername:" because many things in Postfix expect the normal form. TESTING ======= To test, send a piece of e-mail through the MTA doing signing for your domain to one or more of these auto-responders: sa-test@sendmail.net check-auth@verifier.port25.com autorespond+dkim@dk.elandsys.com dktest@exhalus.net dkim-test@altn.com dktest@blackops.org It should be returned to you shortly showing your message in the body of a new message, including all of the header changes that were made in transit. An alternative is to send a message to an email service provider such as Gmail or Yahoo! that is known to verify DKIM signatures, and view the full text of the message you receive there. The message you generated should appear (either at the ESP to which you sent or in the auto-reply you receive) with a DKIM-Signature: header field added containing the signature data from your opendkim filter, and an Authentication-Results: header field that the receiving machine added after verifying the signature. The value of this header field should indicate a "pass". If it doesn't, something in between has altered your message in a way that invalidated the signature. Perhaps you have other filters running that appended to or otherwise modified a header or the message body. The reply from the autoresponder address, or an e-mail sent back to you from your ESP account, will also itself be signed, and in the header of the reply you should see its signature and another Authentication-Results: header field added by your filter, which should also read "pass". LARGE KEYS ========== If you wish to use a large key in DNS, there are some limitations of which you should be aware. A TXT record in the DNS consists of a series of strings each of which don't exceed 255 bytes. This is a result of the fact that each string is preceded by a length byte (which, of course, can't exceed 255). Furthermore, some DNS implementations don't allow packets larger than 512 bytes. Some RSA keys will exceed the 255 byte limit once encoded with base64, so some special formatting must be used to make such a record fit. Failing to do so can cause an incomplete record to be published or, worse, the nameserver to refuse to serve the record or even the entire zone. In the case of the BIND nameserver, there are two syntax rules one can use to make a large record fit within these boundaries: 1) TXT substrings Instead of a record like: recname IN TXT "foobarbazblivitalphabravocharliedelta...zulu" ...one can also do: recname IN TXT "foobar" "baz" "blivit" "alpha" ... "zulu" (The "..." is mean to indicate continuation and is not a literal set of three "." characters.) You simply have to break up the large record into smaller strings such that no string exceeds 255 bytes. DKIM implementations will reassemble TXT records broken down this way into the full original single string before processing them. 2) Line continuations It can be difficult for some to edit very long lines of text. It's therefore desirable to have a mechanism to break very long TXT records down so that they fit nicely within an editor window. In BIND, this is done by enclosing the wrapped lines within parentheses. Continuing with the example above, this: recname IN TXT "foobar" "baz" "blivit" "alpha" ... "zulu" ...can also be expressed as: recname IN TXT ( "foobar" "baz" "blivit" "alpha" "bravo" "charlie" "delta" "echo" ... "yankee" "zulu" ) So using these two techniques, a very large public key could be encoded in a DNS zone file as follows: recname IN TXT ( "v=DKIM1; g=*; k=rsa; " "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Z4F" "JEMHjJDuBmt25zvYFVejlARZGt1L8f0s1+rLxIPYkfCogQi+Y8" "oLEg9vvEKnLx9aogZzuNt6j4Sty3LgXxaIwHnMqk0LldbA/mh3" "wLZb16Wc6btXHON0o3uDipxqGK2iRLTvcgAnNDegseOS+i0aJE" "nNSl663ywRBp/QKezhUC7cnbqR/H8dz8pEOjeawNN3nexdHGsk" "+RaafYvCFvU+70CQORcsk+mxb74SwGT2CGHWxVywQA9yrV+sYk" "JpxaufZLo6xp0Z7RZmbf1eGlCAdhkEy+KYQpQkw2Cdl7iKIK4+" "17gr+XZOrfFLJ5IwpVK/a19m3BLxADf0Kh3oZwIDAQAB" ) DEBUG FEATURES ============== (a) The Canonicalized Content Two configuration file entries are provided to enable detailed debugging and forensics when tracking down failed verifications. These are "KeepTemporaryFiles" and "TemporaryDirectory". When a message is to be signed or verified, its headers and body are passed through a selected canonicalization algorithm. The output of this algorithm is stored in a pair of temporary files if "KeepTemporaryFiles" is enabled. If a verifier and a signer both produce these files, they can be compared after a failed verification to determine how the signed data and verified data differ. "TemporaryDirectory" simply selects the directory to be used to create these files, if other than the default (/tmp) is desired. Recent extensions to DKIM formalized a mechanism by which a signer can ask a verifier to send back copies of these files when verification fails. Specifically, if the failing signature contains an "r=y" tag, then the signer is requesting such feedback. If the verifier is willing to provide it, it makes a second DNS query to find the report destination and packages up the canonicalized forms into a message, which it sends to the named address. The second query goes to the domain named in the signature's "d=" tag, with "_report._domainkey." prepended to it. For example, a failed signature from "example.com" that also had an "r=y" tag would result in a query for a TXT record at "_report._domainkey.example.com". If the reply contains an "ra=" tag, it identifies the requested destination of the report within that same domain (e.g., "ra=foobar" means "send reports to foobar@example.com"). (See RFC 6651 for details.) The signer, on receiving this, can unpack the two files and compare them to the two files it generated for the same message. This comparison usually reveals the change made in transit that invalidated the signature. (b) Diagnostics There are two other features available that are less involved, but also less likely to yield a result. Signers can configure their systems using the "Diagnostics" setting which, if enabled, produces signatures that contain the original header set that was signed. These will be stored in a "z=" tag in the signature. A verifier can extract this information from the signature and, on failed signatures, compare it to the header set that was received and look for discrepancies. If a verifier sets the "DiagnosticDirectory" to name a directory, a file will be generated there whenever a signature bearing a "z=" tag fails to verify, and present the two header sets for visual comparison. Additional detail is provided if the package is compiled with libtre support, as it can identify reordered header fields that differ slightly, and present them alongside each other. REUSING DOMAINKEYS RECORDS ========================== Published DomainKeys key records are almost totally compatible with DKIM. The one area in which they differ is the use of the granularity ("g=") tag. Under DomainKeys, the default granularity is the empty string. DomainKeys interprets this as "match anyone". However, DKIM interprets this as "match none". Thus, a key record containing "g=" means one thing to DomainKeys but the opposite to DKIM, making it incompatible. Under DKIM, the default granularity is "*", which means "match anyone". Since both systems have defaults that mean "match anyone", a DomainKeys key record which doesn't have a "g=" string in it at all will work as expected with DKIM. Thus, if you want to use one key record with both systems, remove the "g=" portion of the record and reload your nameserver. UPGRADING FROM 1.x to 2.x ========================= Configuration files from v1.x.x installations of OpenDKIM are compatible with v2.x.x except for the "KeyList" feature, which has been dropped in favour of a more flexible configuration. The "KeyList" in older versions was a file of this form: pattern:domain:selector:keypath ...where: "pattern" was a pattern to be matched against the From: header field of a message being considered for signing, with the asterisk ("*") character being used as the conventional wildcard "domain" was the domain to be used when generating the signature "selector" was the selector to be used when generating the signature "keypath" was the path to the private key to be used to generate the signature In the newer configuration files, this function has been split into two different files. The first, known as the "KeyTable", maps names of keys to domains, selectors and keys, and the second, known as the "SigningTable", maps sender patterns to entries in the first. So if for example an older installation had the following KeyList: *@example.com:example.com:foo:/var/db/dkim/foo.private *@example.net:example.net:bar:/var/db/dkim/bar.private This would now be split into the two new data sets. In recent versions of OpenDKIM, a data set can be in any of a number of actual forms (SQL databases, flat files, LDAP directories, regular expression files, etc.) so these will be expressed in terms of their data set keys (the item looked up) and values (the item or items returned). So in the new setup, a KeyTable matching the above setup will contain: KEYS VALUES ---- ------ K1 example.com foo /var/db/dkim/foo.private K2 example.net bar /var/db/dkim/bar.private This defines the keys that will be used to sign. Then it is necessary to tell the filter which addresses get signed by which keys, so the SigningTable will contain: KEYS VALUES ---- ------ example.com K1 example.net K2 Consult SigningTable in opendkim.conf(5) man page for a description of the expected keys and values in the SigningTable data set. DATA SETS ========= Several OpenDKIM configuration values describe lists or sets of data, sometimes with associated values. OpenDKIM refers to these as "data sets". They can be stored in a variety of ways such as comma-separated lists, flat files, files involving pattern matching (called "refiles"), Oracle/Sleepycat Berkeley databases (hash or btree), SQL databases, Lua scripts or LDAP directories. For some data sets, merely a test for membership in the set is done. Such entries only have "keys" (items in the set), with no associated "values". `file' and `refile' data sets are nearly identical. Each is a flat file containing two columns separated by whitespace. The left column is the key and the right the value (as described above). If more than one value appears in the right column, then those values should be separated by colons, e.g.: key value1:value2:value3 For example, the difference is that the key column of a `file' SigningTable is matched exactly in the order described in opendkim.conf(5), while the key column of a `refile' SigningTable is a glob-style expression using where "*" is treated as zero or more characters. The `refile' matching syntax is the same as that of an OpenDKIM 1.x KeyList. The `csl' data set works exactly he same way as a `file' data set, but instead of specifying a file to read, it specifies a list of data separated by commas, e.g.: csl:key1 value1,key2 value2 The `bdb' data set simply reads those key/value pairs from a Berkeley-style DB file (also known as a Sleepycat DB) rather than a flat file or list. For LDAP data sets, the search filter and the attributes to be returned should be provided in the LDAP URI. Any instances of `$d' in the LDAP filter will be replaced with the domain or email address being queried for (with the search terms as described above). For instance, a simple SigningTable data set that searches for the "mail" attribute and returns a "keyName" attribute might be: ldap://localhost/dc=example,dc=com?keyName?sub?(mail=$d) The general format for using an LDAP directory in a data set is: ldap://host[:port]/basedn[?attrs[?scope[?filter[?exts]]]] The scheme ldaps:// may be used to connect via SSL, and ldapi:// may be used to connect via UNIX socket. LDAP credentials are stored in the opendkim.conf file. For ODBX (SQL database) data sets, a similar mechanism is used, but the URI must also be tagged with the prefix "dsn:". For the example above, returning columns in a PostgreSQL database instead of LDAP attributes, you might use: dsn:pgsql://username:password@localhost/dkim/table=dkimkeys?keycol=keyName?datacol=mail The general format for using a database in a data set is: dsn:://[user[:pwd]@][port+]host/dbase[/key=val[?...]] The special DSN keys "table", "keycol" and "datacol" are required to name the database from which to select records, the column in which keys will be found, and the column(s) from which their corresponding values should be extracted. A Lua script can be specified as below: lua:/usr/local/keyretrive.lua The Lua script will receive a global variable called "query" which is a string containing the query to be performed. The returned value is the return value of the script. MANUALLY CREATING DKIM KEYS =========================== To manually generate a public and private key: (1 Run this command: openssl genrsa -out rsa.private 1024 This generates a private key and writes it to the file "rsa.private". The generated key is in PEM format and is a 1024-bit key, the minimum required by the DKIM specification. (2) Run this command: openssl rsa -in rsa.private -out rsa.public -pubout -outform PEM This reads the private key generated in the previous step and extracts from it the matching public key. This is written to the file "rsa.public". (3) Add a TXT DNS record containing the base64 encoding of your public key, which is everything between the BEGIN and END lines in the rsa.public file generated above, with spaces and newlines removed. It should be in this form: "v=DKIM1; t=y; p=MFwwDQYJ...AwEAAQ==" ...using, of course, your own public key with is the base64 data from the generated rsa.public file. For a translation of the parameter and value pairs shown here, see the DKIM specification (RFC6376) Section 3.6. The specification is available in a file in the source code package called "rfc6376.txt". Basically this key record just announces an RSA public key and also declares that your site is using this key in test mode so nobody should take any real action based on success or failure of the use of this key to verify a message. NOTE: Key sizes above 2700 bits are unlikely to fit into a 512 byte DNS record. MAILING LISTS ============= Most common mailing list packages (e.g., Mailman) modify messages in different ways; for instance, they add footers to the body, change Reply-to header fields to send replies to the list by default, modify the Subject field to add the mailing list name, and so on. All these modifications are likely to break existing DKIM signatures. If you run a mailing list package, you might want to arrange that all messages generated by the list are signed by DKIM. If you have already configured OpenDKIM in your MTA, follow these steps to also sign mailing list messages: (1) If you are running the list software on a different domain/subdomain (e.g., main domain example.org, mailing lists on lists.example.org), you need to generate a key for that domain as well and add it to the KeyTable (see opendkim.conf(5)). (2) In the SigningTable (see opendkim.conf(5)), you need to add a key corresponding to the mailing list bounce address (e.g., mylist-bounces@lists.example.org) and NOT the list post address; alternatively, you can simply sign the whole domain, adding a key without the local part (e.g., lists.example.org). (3) In opendkim.conf(5), configure the option SenderHeaders to "Sender,From". Usually, OpenDKIM tries to match the contents of only the From field in the SigningTable. With this configuration, it will use the Sender field instead, if it exists. In messages generated by most mailing list software, the Sender field contains the mailing list bounce address, which is the one that needs to be checked in the SigningTable to sign the e-mail; instead, the From address is just the user of the mailing list that wrote the e-mail, which might be writing from a domain not found in the member list. If your mailing list software does not add the Sender field (and cannot be configured to), you can try using the List-Post field instead, though it is less preferable as it is less likely to show up in MUAs. With the above configuration, all bounces generated by the mailing list software should be signed by OpenDKIM. If a user in your domain sends an e-mail to a mailing list in your domain too, the e-mail will contain two DKIM signatures; the first added when the mail was first submitted by the user, and the second added to the message generated by the mailing list software. In this case, the first signature will likely be invalid, but this is perfectly normal; compliant receivers are required to treat an invalid signature as a non-existing signature, thus the message will appear as simply signed once to them. Notice that mailing list software could also be configured to strip the first signature on incoming mail, but this behaviour is considered a bad practice as the signature is totally harmless even if broken, and it can instead be useful for forensic analysis, just like a Received field. SUPPORT ======= There are two public mailing lists available for news and questions about OpenDKIM. To keep up to date on the latest developments, please subscribe to one or both of the following: opendkim-announce@lists.opendkim.org (release announcements) opendkim-users@lists.opendkim.org (general discussion) Send an email to opendkim-announce-request@lists.opendkim.org with subscribe as the subject to receive release announcements. You can find more information about our mailing lists at http://www.opendkim.org. To report bugs and feature requests, you can access the SourceForge "tracker" facilities at http://sourceforge.net/projects/opendkim. OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/README.SQL000066400000000000000000000111371337314105200216040ustar00rootroot00000000000000OPENDKIM SQL NOTES ================== Contributed by Todd Lyons The OpenDKIM filter ("opendkim") supports numerous types of databases for storing configuration information. See the opendkim(8) man page for a summary of the possibilities. Certain data sets are expected to return multiple values in response to a single query. The KeyTable is a common example of this. Configuring these for SQL or LDAP backends can be tricky. This document explains them in some detail and provides a few example configurations. The SigningTable lookup will use a signing pattern based on the message sender to perform a lookup and must return an arbitrary "label", which can be any string or number you wish to use. The KeyTable lookup will use this label to search for and return the following three pieces of data, in this order: domain name, selector, private key (in ASCII armor, or a filename) In the simplest configuration, where you want to sign all emails for a domain, all data can exist in the same table. For this simplest configuration example, assume that a table called "dkim" has these fields: `id` int(10) unsigned NOT NULL auto_increment, `domain_name` varchar(255) NOT NULL, `selector` varchar(63) NOT NULL, `private_key` text, `public_key` text, INDEX(domain_name) A sample opendkim configuration that references a MySQL database could look like this: SigningTable dsn:mysql://USER:PASSWORD@SERVER/DBNAME/table=dkim?keycol=domain_name?datacol=id KeyTable dsn:mysql://USER:PASSWORD@SERVER/DBNAME/table=dkim?keycol=id?datacol=domain_name,selector,private_key The strings USER, PASSWORD, SERVER and DBNAME would be replaced by the name of the database user to be used, that user's database password, the hostname where the server can be contacted, and the name of the database at that server to be used, respectively. The above data sets would then map to the following SQL queries: SELECT id FROM dkim WHERE domain_name='the_signing_pattern'; SELECT domain_name,selector,private_key FROM dkim WHERE id='previous_answer'; In the first query, the answer returned (the "arbitrary label") is the ID of the record that matches the signing pattern. Since the intent is to sign all records for that domain, the domain name is what queried. The ID is used to then lookup the domain name to sign with, the selector, and the private key. For example, a message from "user@example.com" with the above setup would cause the following SigningTable queries: SELECT id FROM dkim WHERE domain_name='user@example.com'; SELECT id FROM dkim WHERE domain_name='example.com'; SELECT id FROM dkim WHERE domain_name='user@.com'; SELECT id FROM dkim WHERE domain_name='.com'; SELECT id FROM dkim WHERE domain_name='user@*'; SELECT id FROM dkim WHERE domain_name='*'; If there is no match to any of these, then the SigningTable will not result in a signature being added to the message. Suppose one of these returns a value of 1293 for 'id'. This is then fed to a query to the KeyTable data set, resulting in the following query: SELECT domain_name,selector,private_key FROM dkim WHERE id='1293'; The content of those three fields are then used to construct the signature on the message. In a medium complicated setup, such as one where you potentially want to specify different keys based on email address or subdomain name, this is best implemented with two tables. First, the "dkim" table above, then a second table which will tie distinct labels to the domain/selector/key tuple. As an example, this second table, named 'dkim_signing', might have these fields: `id` int(10) unsigned NOT NULL auto_increment, `author` varchar(255) NOT NULL, `dkim_id` unsigned NOT NULL, INDEX(author) The resulting opendkim configuration would be: SigningTable dsn:mysql://USER:PASSWORD@SERVER/DB/table=dkim_signing?keycol=author?datacol=dkim_id KeyTable dsn:mysql://USER:PASSWORD@SERVER/DB/table=dkim?keycol=id?datacol=domain_name,selector,private_key ...which maps to the following SQL queries: SELECT dkim_id FROM dkim_signing WHERE author='the_signing_pattern'; SELECT domain_name,selector,private_key FROM dkim WHERE id='previous_answer'; One other advantage of this medium complicated setup is that you could define one key and have multiple authors in the signing table that point to it (called a "Many-To-One" relationship). In summary, this many-to-one concept is the same as using flat files, but with the added advantage that the data is stored in a central location that multiple mail servers can access, and the signing and key configuration can be modified by changing the SQL data without disturbing the filter itself in any way. OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/autorespond.csh000066400000000000000000000020141337314105200233220ustar00rootroot00000000000000#!/bin/csh -f ## ## ## Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers. ## All rights reserved. ## ## Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. ## ## autorespond.csh -- accept a message and reply to it to test signing and ## verifying of opendkim ## Setup set infile=/tmp/ari.$$ set tmpfile=/tmp/aro.$$ set hostname=`hostname` ## Capture the incoming message cat > $infile ## Build the reply echo From: autorespond@$hostname >> $tmpfile grep '^From:' < $infile | sed 's/^From/To/g' >> $tmpfile ## Enable the next line to allow remote canonicalization selection: # grep '^X-Canonicalization:' < $infile >> $tmpfile echo Subject: Auto-response from $hostname >> $tmpfile echo "" >> $tmpfile echo "Original message:" >> $tmpfile echo "" >> $tmpfile cat $infile >> $tmpfile echo "" >> $tmpfile echo "And some random data:" >> $tmpfile echo "" >> $tmpfile dd if=/dev/urandom count=10 | base64 -e >> $tmpfile ## Send the reply sendmail -t < $tmpfile ## Clean up rm -f $tmpfile $infile exit 0 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/config.c000066400000000000000000000356261337314105200217100ustar00rootroot00000000000000/* ** Copyright (c) 2006-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* _REENTRANT */ /* system includes */ #include #include #include #include #include /* libopendkim includes */ #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "config.h" /* limits */ #define BUFRSZ 1024 /* generic buffer size */ #define MAXLEVEL 5 /* max. include recursion */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* prototypes */ static void config_attach __P((struct config *, struct config **)); /* errors */ #define CONF_UNKNOWN (-1) /* unknown status */ #define CONF_SUCCESS 0 /* no error */ #define CONF_MISSING 1 /* required value missing */ #define CONF_UNRECOG 2 /* unrecognized parameter */ #define CONF_ILLEGAL 3 /* illegal value */ #define CONF_NESTING 4 /* "include" nesting too deep */ #define CONF_READING 5 /* error reading (see errno) */ #define CONF_NMEMORY 6 /* malloc() failure */ /* statics */ static int conf_error; /* configuration error number */ /* ** CONFIG_GETLINE -- read a line of arbitary length from a stream ** ** Parameters: ** in -- input stream ** ** Return value: ** NULL on EOF, otherwise a newly-allocated string containing the next ** line from "in". */ static char * config_getline(FILE *in) { int c; size_t asize = BUFRSZ; size_t len = 0; char *new = NULL; assert(in != NULL); new = malloc(asize); if (new == NULL) return NULL; new[0] = '\0'; for (;;) { c = fgetc(in); if (c == '\n') { break; } else if (c == EOF) { if (len == 0) { free(new); new = NULL; } break; } if (len == asize - 1) { char *newnew; asize += BUFRSZ; newnew = realloc(new, asize); if (newnew == NULL) { free(new); return NULL; } new = newnew; } new[len++] = c; new[len] = '\0'; } return new; } /* ** CONFIG_ATTACH -- attach one config to another ** ** Parameters: ** c1 -- configuration to attach ** c2 -- configuration to which to attach ** ** Return value: ** None. */ static void config_attach(struct config *c1, struct config **c2) { struct config *prev; struct config *cur; assert(c1 != NULL); if (*c2 == NULL) { *c2 = c1; } else { prev = NULL; for (cur = c1; cur != NULL; cur = cur->cfg_next) prev = cur; prev->cfg_next = *c2; } } /* ** CONFIG_LOAD_LEVEL -- load configuration from a file (internal version) ** ** Parameters: ** file -- path from which to load; NULL or "-" implies stdin ** cd -- array of (struct configdef) elements containing the ** configuration syntax to assert ** line -- line number where an error occurred (updated) ** outpath -- configuration file in which error occurred (updated) ** outpathlen -- bytes available at "outpath" ** level -- nesting level ** deprecated -- string containing list of deprecated items (updated) ** ** Return value: ** Pointer to a (struct config) which is the head of a list of ** loaded configuration items, or NULL on error; if NULL, "line" is ** updated to indicate which line number contained the error and, ** if the configuration file being parsed was not the one referenced ** by "in", then "path" will be updated to point to the filename ** that was being processed. */ static struct config * config_load_level(char *file, struct configdef *def, unsigned int *line, char *outpath, size_t outpathlen, int level, char **deprecated) { int n = -1; int err = 0; unsigned int myline = 0; int value = -1; FILE *in; char *p; char *s; char *str = NULL; char *buf; struct config *new = NULL; struct config *cur = NULL; assert(def != NULL); if (level > MAXLEVEL) { conf_error = CONF_NESTING; return NULL; } if (file == NULL || (file[0] == '-' && file[1] == '\0')) { in = stdin; file = "(stdin)"; } else { in = fopen(file, "r"); if (in == NULL) { conf_error = CONF_READING; if (line != NULL) *line = myline; if (outpath != NULL) strlcpy(outpath, file, outpathlen); return NULL; } } while ((buf = config_getline(in)) != NULL) { myline++; str = NULL; /* read a line; truncate at carriage return, newline, or "#" */ for (p = buf; *p != '\0'; p++) { if (*p == '#' || *p == 0x0D) { *p = '\0'; break; } } /* break down the line */ p = strtok_r(buf, " \t", &s); if (p != NULL) { /* recognize the directive? */ for (n = 0; ; n++) { /* nope */ if (def[n].cd_name == NULL) { conf_error = CONF_UNRECOG; err = 1; break; } if (strcasecmp(def[n].cd_name, p) == 0) break; } if (!err) { char *q; /* skip leading whitespace on value */ for (p = s; *p == ' ' || *p == '\t'; p++) continue; /* ...and trim trailing whitespace */ q = p + strlen(p) - 1; while (p <= q && (*q == '\t' || *q == ' ')) *q-- = '\0'; } if (*p == '\0' && !err) { conf_error = CONF_MISSING; err = 1; } if (!err) { char *q; switch (def[n].cd_type) { case CONFIG_TYPE_DEPRECATED: if (deprecated == NULL) { break; } else if (*deprecated == NULL) { *deprecated = strdup(def[n].cd_name); } else { char *new; size_t oldlen; size_t newlen; oldlen = strlen(*deprecated); newlen = oldlen + 2 + strlen(def[n].cd_name); new = realloc(*deprecated, newlen); if (new != NULL) { new[oldlen] = ','; new[oldlen + 1] = '\0'; strlcat(*deprecated, def[n].cd_name, newlen); *deprecated = new; } } break; case CONFIG_TYPE_STRING: case CONFIG_TYPE_INCLUDE: str = p; break; case CONFIG_TYPE_BOOLEAN: if (p[0] == 't' || p[0] == 'T' || p[0] == 'y' || p[0] == 'Y' || p[0] == '1') { value = 1; } else if (p[0] == 'f' || p[0] == 'F' || p[0] == 'n' || p[0] == 'N' || p[0] == '0') { value = 0; } else { conf_error = CONF_ILLEGAL; err = 1; } break; case CONFIG_TYPE_INTEGER: value = (int) strtol(p, &q, 0); if (*q != '\0') { conf_error = CONF_ILLEGAL; err = 1; } str = p; break; default: assert(0); /* NOTREACHED */ return NULL; } } } else { free(buf); continue; /* blank line */ } /* a parse error, or only one argument, is no good */ if (err) { config_free(cur); if (line != NULL) *line = myline; if (outpath != NULL) strlcpy(outpath, file, outpathlen); if (in != stdin) fclose(in); free(buf); return NULL; } if (def[n].cd_type != CONFIG_TYPE_INCLUDE && def[n].cd_type != CONFIG_TYPE_DEPRECATED) { new = (struct config *) malloc(sizeof(struct config)); if (new == NULL) { config_free(cur); conf_error = CONF_NMEMORY; if (line != NULL) *line = myline; if (outpath != NULL) strlcpy(outpath, file, outpathlen); if (in != stdin) fclose(in); free(buf); return NULL; } new->cfg_next = cur; new->cfg_name = def[n].cd_name; new->cfg_type = def[n].cd_type; } switch (def[n].cd_type) { case CONFIG_TYPE_INCLUDE: { struct config *incl; incl = config_load_level(str, def, line, outpath, outpathlen, level + 1, deprecated); if (incl == NULL) { if (in != stdin) fclose(in); free(buf); return NULL; } config_attach(incl, &cur); new = incl; break; } case CONFIG_TYPE_STRING: new->cfg_string = strdup(str); break; case CONFIG_TYPE_BOOLEAN: new->cfg_bool = (_Bool) value; break; case CONFIG_TYPE_INTEGER: new->cfg_int = value; break; case CONFIG_TYPE_DEPRECATED: break; default: assert(0); } cur = new; free(buf); } conf_error = CONF_SUCCESS; if (in != stdin) fclose(in); if (myline == 0 || cur == NULL) { cur = (struct config *) malloc(sizeof *cur); if (cur != NULL) { cur->cfg_bool = FALSE; cur->cfg_type = CONFIG_TYPE_STRING; cur->cfg_int = 0; cur->cfg_name = ""; cur->cfg_string = NULL; cur->cfg_next = NULL; return cur; } else { conf_error = CONF_NMEMORY; if (line != NULL) *line = myline; if (outpath != NULL) strlcpy(outpath, file, outpathlen); return NULL; } } else { return cur; } } /* ** CONFIG_ERROR -- return a string describing a configuration error ** ** Parameters: ** None. ** ** Return value: ** Pointer to a NULL-terminated string explaining the last error. */ char * config_error(void) { switch (conf_error) { case CONF_SUCCESS: return "no error"; case CONF_MISSING: return "required value missing"; case CONF_UNRECOG: return "unrecognized parameter"; case CONF_ILLEGAL: return "illegal value"; case CONF_NESTING: return "nesting too deep"; case CONF_READING: return "error reading configuration file"; case CONF_NMEMORY: return "memory allocation failure"; case CONF_UNKNOWN: default: return "unknown error"; } /* NOTREACHED */ } /* ** CONFIG_FREE -- release memory associated with a config list ** ** Parameters: ** head -- head of the config list ** ** Return value: ** None. */ void config_free(struct config *head) { struct config *next; struct config *cur; cur = head; while (cur != NULL) { next = cur->cfg_next; if (cur->cfg_type == CONFIG_TYPE_STRING && cur->cfg_string != NULL) free(cur->cfg_string); free(cur); cur = next; } } /* ** CONFIG_LOAD -- load configuration from a file ** ** Parameters: ** file -- path from which to load; NULL or "-" implies stdin ** cd -- array of (struct configdef) elements containing the ** configuration syntax to assert ** line -- line number where an error occurred (updated) ** path -- configuration file in which error occurred (updated) ** pathlen -- number of bytes available at "path" ** ** Return value: ** Pointer to a (struct config) which is the head of a list of ** loaded configuration items, or NULL on error; if NULL, "line" is ** updated to indicate which line number contained the error and, ** if the configuration file being parsed was not the one referenced ** by "in", then "path" will be updated to point to the filename ** that was being processed. */ struct config * config_load(char *file, struct configdef *def, unsigned int *line, char *path, size_t pathlen, char **deprecated) { conf_error = CONF_UNKNOWN; return config_load_level(file, def, line, path, pathlen, 0, deprecated); } /* ** CONFIG_CHECK -- verify that stuff marked "required" is present ** ** Parameters: ** head -- head of config list ** def -- definitions ** ** Return value: ** Name of the first parameter in "def" that was marked "required" ** yet absent from the configuration parsed, or NULL if nothing ** required was missing. */ char * config_check(struct config *head, struct configdef *def) { int n; struct config *cur; assert(head != NULL); assert(def != NULL); conf_error = CONF_UNKNOWN; for (n = 0; ; n++) { if (def[n].cd_name == NULL) { conf_error = CONF_SUCCESS; return NULL; } if (!def[n].cd_req) continue; for (cur = head; cur != NULL; cur = cur->cfg_next) { if (cur->cfg_name == def[n].cd_name) break; } if (cur == NULL) { conf_error = CONF_MISSING; return def[n].cd_name; } } /* NOTREACHED */ } /* ** CONFIG_GET -- retrieve a parameter's value ** ** Parameter: ** head -- head of config list ** name -- name of the parameter of interest ** value -- where to write the result (returned) ** size -- bytes available at "value" ** ** Return value: ** 1 if the data was found, 0 otherwise, -1 if the request was illegal ** ** Notes: ** "value" is a (void *). It can be used directly, such as: ** ** int x; ** ** (void) config_get(conflist, "MyInteger", (void *) &x); */ int config_get(struct config *head, const char *name, void *value, size_t size) { struct config *cur; assert(head != NULL); assert(name != NULL); assert(value != NULL); assert(size > 0); conf_error = CONF_UNKNOWN; for (cur = head; cur != NULL; cur = cur->cfg_next) { if (strcasecmp(cur->cfg_name, name) == 0) { switch (cur->cfg_type) { case CONFIG_TYPE_BOOLEAN: if (size != sizeof(_Bool)) { conf_error = CONF_ILLEGAL; return -1; } memcpy(value, &cur->cfg_bool, size); break; case CONFIG_TYPE_INTEGER: if (size != sizeof(int)) { conf_error = CONF_ILLEGAL; return -1; } memcpy(value, &cur->cfg_int, size); break; case CONFIG_TYPE_INCLUDE: conf_error = CONF_ILLEGAL; return -1; default: if (size != sizeof(char *)) { conf_error = CONF_ILLEGAL; return -1; } memcpy(value, &cur->cfg_string, size); break; } return 1; } } conf_error = CONF_SUCCESS; return 0; } /* ** CONFIG_VALIDNAME -- return True IFF the name provided was valid ** ** Parameters: ** def -- configuration definition ** name -- name of value of interest ** ** Return value: ** True IFF "name" was defined inside "cd" */ _Bool config_validname(struct configdef *def, const char *name) { unsigned int n; assert(def != NULL); assert(name != NULL); for (n = 0; ; n++) { if (def[n].cd_name == NULL) return FALSE; if (strcasecmp(name, def[n].cd_name) == 0 && def[n].cd_type != CONFIG_TYPE_DEPRECATED) return TRUE; } assert(0); /* NOTREACHED */ } /* ** CONFIG_DUMP -- dump configuration contents ** ** Parameters: ** cfg -- head of assembled configuration values ** out -- stream to which to write ** name -- name of value of interest ** ** Return value: ** Number of items that matched. */ unsigned int config_dump(struct config *cfg, FILE *out, const char *name) { unsigned int nprinted = 0; struct config *cur; assert(cfg != NULL); assert(out != NULL); for (cur = cfg; cur != NULL; cur = cur->cfg_next) { if (name != NULL) { if (strcasecmp(name, cur->cfg_name) != 0) continue; } else { fprintf(out, "%p: \"%s\" ", cur, cur->cfg_name); } switch (cur->cfg_type) { case CONFIG_TYPE_STRING: fprintf(out, "%s\n", cur->cfg_string); break; case CONFIG_TYPE_INTEGER: fprintf(out, "%d\n", cur->cfg_int); break; case CONFIG_TYPE_BOOLEAN: fprintf(out, "%s\n", cur->cfg_bool ? "True" : "False"); break; default: assert(0); } nprinted++; } return nprinted; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/config.h000066400000000000000000000025041337314105200217020ustar00rootroot00000000000000/* ** Copyright (c) 2006-2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, 2015, The Trusted Domain Project. All rights reserved. ** */ #ifndef _CONFIG_H_ #define _CONFIG_H_ #include "build-config.h" /* system includes */ #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include /* types and things */ #define CONFIG_TYPE_STRING 0 #define CONFIG_TYPE_INTEGER 1 #define CONFIG_TYPE_BOOLEAN 2 #define CONFIG_TYPE_INCLUDE 3 #define CONFIG_TYPE_DEPRECATED 4 struct config { _Bool cfg_bool; u_int cfg_type; int cfg_int; char * cfg_name; char * cfg_string; struct config * cfg_next; }; struct configdef { char * cd_name; u_int cd_type; u_int cd_req; }; /* prototypes */ extern char *config_check __P((struct config *, struct configdef *)); extern unsigned int config_dump __P((struct config *, FILE *, const char *)); extern char *config_error __P((void)); extern void config_free __P((struct config *)); extern int config_get __P((struct config *, const char *, void *, size_t)); extern struct config *config_load __P((char *, struct configdef *, unsigned int *, char *, size_t, char **)); extern _Bool config_validname __P((struct configdef *, const char *)); #endif /* _CONFIG_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/final.lua.sample000066400000000000000000000040501337314105200233360ustar00rootroot00000000000000-- -- Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. -- All rights reserved. -- -- final.lua.sample -- sample version of the "final" script that demonstrates -- all of the features of the configuration file -- -- The final script is executed after the entire message body has been -- received and processed but before the filter renders its final verdict. -- The main use of this script is to determine whether or not the message -- is acceptable to the verifier, and what final filtering action should be -- taken. For exmaple, if the message failed Author Domain Signing -- Practises tests, or had additional data appended to it beyond what the -- signature covered, or even if the signature simply failed to verify, -- this script can detect such things and take whatever action is desired. -- Retrieve signature count nsigs = odkim.get_sigcount(ctx) if nsigs == nil then return nil end -- Enact ADSP. -- 1) If it reported NXDOMAIN, reject. if odkim.get_presult(ctx) == DKIM_PRESULT_NXDOMAIN then odkim.set_reply(ctx, "554", "5.7.1", "sender domain does not exist") odkim.set_result(ctx, SMFIS_REJECT) return nil end -- 2) Test for discardable. We'll handle "unknown" and "all" through RFC5451. if odkim.get_presult(ctx) == DKIM_PRESULT_FOUND and odkim.get_policy(ctx) == DKIM_POLICY_DISCARDABLE then discard = true for n = 1, nsigs sig = odkim.get_sighandle(ctx, n) sigres = odkim.sig_result(sig) sdomain = odkim.sig_getdomain(sig) if sigres == 0 and sdomain == fromdomain then discard = false end end if discard then odkim.set_result(ctx, SMFIS_REJECT) return nil end end -- If the message had too much stuff added to it (more than 120 bytes) -- then bounce it for n = 1, nsigs do sig = odkim.get_sighandle(ctx, n) bodylen = odkim.sig_bodylength(sig) canonlen = odkim.sig_canonlength(sig) if bodylen > canonlen + 120 then odkim.set_reply(ctx, "554", "", "Too much data after DKIM-protected body") odkim.set_result(ctx, SMFIS_REJECT) end end -- That's it! return nil OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/flowrate.c000066400000000000000000000057421337314105200222620ustar00rootroot00000000000000/* ** Copyright (c) 2011-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" #ifdef _FFR_RATE_LIMIT /* system includes */ #include #include #include #include #include #include #include #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "flowrate.h" #include "opendkim.h" #include "opendkim-db.h" /* DATA TYPES */ struct flowdata { time_t fd_since; unsigned int fd_limit; unsigned int fd_count; }; /* GLOBALS */ pthread_mutex_t ratelock; /* ** DKIMF_RATE_CHECK -- conduct a rate limit check, expire data, increment ** ** Parameters: ** domain -- domain name being queried (or NULL for unsigned mail) ** ratedb -- data set containing per-domain rate limits ** flowdb -- data set containing per-domain flow data (updated) ** factor -- divisor ** ttl -- TTL to apply (i.e. data expiration) ** limit -- limit for this domain (returned) ** ** Return value: ** -1 -- error ** 0 -- success ** 1 -- success, and the domain is at or past its limit */ int dkimf_rate_check(const char *domain, DKIMF_DB ratedb, DKIMF_DB flowdb, int factor, int ttl, unsigned int *limit) { _Bool found = FALSE; int status; time_t now; struct dkimf_db_data dbd; struct flowdata f; char limbuf[BUFRSZ]; assert(ratedb != NULL); assert(flowdb != NULL); if (domain == NULL) domain = "."; memset(&f, '\0', sizeof f); pthread_mutex_lock(&ratelock); /* get the current flow data, if any */ dbd.dbdata_buffer = (void *) &f; dbd.dbdata_buflen = sizeof f; dbd.dbdata_flags = DKIMF_DB_DATA_BINARY; status = dkimf_db_get(flowdb, (void *) domain, 0, &dbd, 1, &found); if (status != 0) { pthread_mutex_unlock(&ratelock); return -1; } (void) time(&now); /* if none or if it expired, retrieve the limit */ if (!found || f.fd_since + ttl <= now) { char *p; dbd.dbdata_buffer = limbuf; dbd.dbdata_buflen = sizeof limbuf; dbd.dbdata_flags = 0; status = dkimf_db_get(ratedb, (void *) domain, 0, &dbd, 1, &found); if (status != 0) { pthread_mutex_unlock(&ratelock); return -1; } else if (!found) { pthread_mutex_unlock(&ratelock); return 0; } f.fd_count = 0; f.fd_limit = (unsigned int) strtoul(limbuf, &p, 10) / factor; (void) time(&f.fd_since); if (*p != '\0') { pthread_mutex_unlock(&ratelock); return -1; } } /* increment the count */ f.fd_count++; /* write it back out */ status = dkimf_db_put(flowdb, (void *) domain, strlen(domain), &f, sizeof f); if (status != 0) { pthread_mutex_unlock(&ratelock); return -1; } pthread_mutex_unlock(&ratelock); /* copy the limit out */ if (limit != NULL) *limit = f.fd_limit; return (f.fd_count >= f.fd_limit ? 1 : 0); } #endif /* _FFR_RATE_LIMIT */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/flowrate.h000066400000000000000000000011471337314105200222620ustar00rootroot00000000000000/* ** Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. */ #ifndef _FLOWRATE_H_ #define _FLOWRATE_H_ #include "build-config.h" /* system includes */ #include #include /* opendkim includes */ #include "opendkim-db.h" #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* prototypes */ extern int dkimf_rate_check __P((const char *, DKIMF_DB, DKIMF_DB, int, int, unsigned int *)); #endif /* _FLOWRATE_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-ar.c000066400000000000000000000325001337314105200226350ustar00rootroot00000000000000/* ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011-2014, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #ifdef ARTEST # include #endif /* ARTEST */ /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "opendkim-ar.h" /* macros */ #define ARES_ENDOF(x) ((x) + sizeof(x) - 1) #define ARES_STRORNULL(x) ((x) == NULL ? "(null)" : (x)) #define ARES_TOKENS ";=." #define ARES_TOKENS2 "=." #define ARES_MAXTOKENS 512 /* tables */ struct lookup { char * str; int code; }; struct lookup methods[] = { { "auth", ARES_METHOD_AUTH }, { "dkim", ARES_METHOD_DKIM }, { "dkim-adsp", ARES_METHOD_DKIMADSP }, { "dkim-atps", ARES_METHOD_DKIMATPS }, { "dmarc", ARES_METHOD_DMARC }, { "domainkeys", ARES_METHOD_DOMAINKEYS }, { "iprev", ARES_METHOD_IPREV }, { "rrvs", ARES_METHOD_RRVS }, { "sender-id", ARES_METHOD_SENDERID }, { "smime", ARES_METHOD_SMIME }, { "spf", ARES_METHOD_SPF }, { NULL, ARES_METHOD_UNKNOWN } }; struct lookup aresults[] = { { "none", ARES_RESULT_NONE }, { "pass", ARES_RESULT_PASS }, { "fail", ARES_RESULT_FAIL }, { "policy", ARES_RESULT_POLICY }, { "neutral", ARES_RESULT_NEUTRAL }, { "temperror", ARES_RESULT_TEMPERROR }, { "permerror", ARES_RESULT_PERMERROR }, { "nxdomain", ARES_RESULT_NXDOMAIN }, { "signed", ARES_RESULT_SIGNED }, { "unknown", ARES_RESULT_UNKNOWN }, { "discard", ARES_RESULT_DISCARD }, { "softfail", ARES_RESULT_SOFTFAIL }, { NULL, ARES_RESULT_UNKNOWN } }; struct lookup ptypes[] = { { "smtp", ARES_PTYPE_SMTP }, { "header", ARES_PTYPE_HEADER }, { "body", ARES_PTYPE_BODY }, { "policy", ARES_PTYPE_POLICY }, { NULL, ARES_PTYPE_UNKNOWN } }; /* ** ARES_TOKENIZE -- tokenize a string ** ** Parameters: ** input -- input string ** outbuf -- output buffer ** outbuflen -- number of bytes available at "outbuf" ** tokens -- array of token pointers ** ntokens -- number of token pointers available at "tokens" ** ** Return value: ** -1 -- not enough space at "outbuf" for tokenizing ** other -- number of tokens identified; may be greater than ** "ntokens" if there were more tokens found than there were ** pointers available. */ static int ares_tokenize(u_char *input, u_char *outbuf, size_t outbuflen, u_char **tokens, int ntokens) { _Bool quoted = FALSE; _Bool escaped = FALSE; _Bool intok = FALSE; int n = 0; int parens = 0; u_char *p; u_char *q; u_char *end; assert(input != NULL); assert(outbuf != NULL); assert(outbuflen > 0); assert(tokens != NULL); assert(ntokens > 0); q = outbuf; end = outbuf + outbuflen - 1; for (p = input; *p != '\0' && q <= end; p++) { if (escaped) /* escape */ { if (!intok) { if (n < ntokens) tokens[n] = q; intok = TRUE; } *q = *p; q++; escaped = FALSE; } else if (*p == '\\') /* escape */ { escaped = TRUE; } else if (*p == '"' && parens == 0) /* quoting */ { quoted = !quoted; if (!intok) { if (n < ntokens) tokens[n] = q; intok = TRUE; } } else if (*p == '(' && !quoted) /* "(" (comment) */ { parens++; if (!intok) { if (n < ntokens) tokens[n] = q; intok = TRUE; } *q = *p; q++; } else if (*p == ')' && !quoted) /* ")" (comment) */ { if (parens > 0) { parens--; if (parens == 0) { intok = FALSE; n++; *q = ')'; q++; if (q <= end) { *q = '\0'; q++; } } } } else if (quoted) /* quoted character */ { *q = *p; q++; } else if (isascii(*p) && isspace(*p)) /* whitespace */ { if (quoted || parens > 0) { if (intok) { *q = *p; q++; } } else if (intok) { intok = FALSE; *q = '\0'; q++; n++; } } else if (strchr(ARES_TOKENS, *p) != NULL) /* delimiter */ { if (parens > 0) { *q = *p; q++; continue; } if (intok) { intok = FALSE; *q = '\0'; q++; n++; } if (q <= end) { *q = *p; if (n < ntokens) { tokens[n] = q; n++; } q++; } if (q <= end) { *q = '\0'; q++; } } else /* other */ { if (!intok) { if (n < ntokens) tokens[n] = q; intok = TRUE; } *q = *p; q++; } } if (q >= end) return -1; if (intok) { *q = '\0'; n++; } return n; } /* ** ARES_CONVERT -- convert a string to its code ** ** Parameters: ** table -- in which table to look up ** str -- string to find ** ** Return value: ** A code translation of "str". */ static int ares_convert(struct lookup *table, char *str) { int c; assert(table != NULL); assert(str != NULL); for (c = 0; ; c++) { if (table[c].str == NULL || strcasecmp(table[c].str, str) == 0) return table[c].code; } /* NOTREACHED */ } #ifdef ARTEST /* ** ARES_XCONVERT -- convert a code to its string ** ** Parameters: ** table -- in which table to look up ** code -- code to find ** ** Return value: ** A string translation of "code". */ static char * ares_xconvert(struct lookup *table, int code) { int c; assert(table != NULL); for (c = 0; ; c++) { if (table[c].str == NULL || table[c].code == code) return table[c].str; } /* NOTREACHED */ } #endif /* ARTEST */ /* ** ARES_DEDUP -- if we've gotten multiple results of the same method, ** discard the older one ** ** Parameters: ** ar -- pointer to a (struct authres) ** n -- the last one that was loaded ** ** Return value: ** TRUE iff a de-duplication happened, leaving the result referenced by ** "n" open. */ _Bool ares_dedup(struct authres *ar, int n) { int c; for (c = 0; c < n; c++) { if (ar->ares_result[c].result_method == ar->ares_result[n].result_method && ar->ares_result[c].result_method != ARES_METHOD_DKIM) { memcpy(&ar->ares_result[c], &ar->ares_result[n], sizeof(ar->ares_result[c])); return TRUE; } } return FALSE; } /* ** ARES_PARSE -- parse an Authentication-Results: header, return a ** structure containing a parsed result ** ** Parameters: ** hdr -- NULL-terminated contents of an Authentication-Results: ** header field ** ar -- a pointer to a (struct authres) loaded by values after parsing ** ** Return value: ** 0 on success, -1 on failure. */ int ares_parse(u_char *hdr, struct authres *ar) { int n; int ntoks; int c; int r = 0; int state; int prevstate; u_char tmp[DKIM_MAXHEADER + 2]; u_char *tokens[ARES_MAXTOKENS]; assert(hdr != NULL); assert(ar != NULL); memset(ar, '\0', sizeof *ar); memset(tmp, '\0', sizeof tmp); ntoks = ares_tokenize(hdr, tmp, sizeof tmp, tokens, ARES_MAXTOKENS); if (ntoks == -1 || ntoks > ARES_MAXTOKENS) return -1; prevstate = -1; state = 0; n = 0; for (c = 0; c < ntoks; c++) { if (tokens[c][0] == '(') /* comment */ continue; switch (state) { case 0: /* authserv-id */ if (!isascii(tokens[c][0]) || !isalnum(tokens[c][0])) return -1; if (tokens[c][0] == ';') { prevstate = state; state = 3; } else { strlcat((char *) ar->ares_host, (char *) tokens[c], sizeof ar->ares_host); prevstate = state; state = 1; } break; case 1: /* [version] */ if (tokens[c][0] == '.' && tokens[c][1] == '\0' && prevstate == 0) { strlcat((char *) ar->ares_host, (char *) tokens[c], sizeof ar->ares_host); prevstate = state; state = 0; break; } if (tokens[c][0] == ';') { prevstate = state; state = 3; } else if (isascii(tokens[c][0]) && isdigit(tokens[c][0])) { strlcpy((char *) ar->ares_version, (char *) tokens[c], sizeof ar->ares_version); prevstate = state; state = 2; } else { return -1; } break; case 2: /* ; */ if (tokens[c][0] != ';' || tokens[c][1] != '\0') return -1; prevstate = state; state = 3; break; case 3: /* method */ if (n == 0 || !ares_dedup(ar, n)) n++; if (n >= MAXARESULTS) return 0; r = 0; ar->ares_result[n - 1].result_method = ares_convert(methods, (char *) tokens[c]); prevstate = state; state = 4; break; case 4: /* = */ if (tokens[c][0] != '=' || tokens[c][1] != '\0') return -1; prevstate = state; state = 5; break; case 5: /* result */ ar->ares_result[n - 1].result_result = ares_convert(aresults, (char *) tokens[c]); prevstate = state; state = 6; break; case 7: /* = (reason) */ if (tokens[c][0] != '=' || tokens[c][1] != '\0') return -1; prevstate = state; state = 8; break; case 8: strlcpy((char *) ar->ares_result[n - 1].result_reason, (char *) tokens[c], sizeof ar->ares_result[n - 1].result_reason); prevstate = state; state = 9; break; case 6: /* reason/propspec */ if (tokens[c][0] == ';' && /* neither */ tokens[c][1] == '\0') { prevstate = state; state = 3; continue; } if (strcasecmp((char *) tokens[c], "reason") == 0) { /* reason */ prevstate = state; state = 7; continue; } else { prevstate = state; state = 9; } /* FALLTHROUGH */ case 9: /* ptype */ if (prevstate == 13 && strchr(ARES_TOKENS2, tokens[c][0]) != NULL && tokens[c][1] == '\0') { r--; strlcat((char *) ar->ares_result[n - 1].result_value[r], (char *) tokens[c], sizeof ar->ares_result[n - 1].result_value[r]); prevstate = state; state = 13; continue; } if (tokens[c][0] == ';' && tokens[c][1] == '\0') { prevstate = state; state = 3; continue; } else { ares_ptype_t x; x = ares_convert(ptypes, (char *) tokens[c]); if (x == ARES_PTYPE_UNKNOWN) return -1; if (r < MAXPROPS) ar->ares_result[n - 1].result_ptype[r] = x; prevstate = state; state = 10; } break; case 10: /* . */ if (tokens[c][0] != '.' || tokens[c][1] != '\0') return -1; prevstate = state; state = 11; break; case 11: /* property */ if (r < MAXPROPS) { strlcpy((char *) ar->ares_result[n - 1].result_property[r], (char *) tokens[c], sizeof ar->ares_result[n - 1].result_property[r]); } prevstate = state; state = 12; break; case 12: /* = */ if (tokens[c][0] != '=' || tokens[c][1] != '\0') return -1; prevstate = state; state = 13; break; case 13: /* value */ if (r < MAXPROPS) { strlcat((char *) ar->ares_result[n - 1].result_value[r], (char *) tokens[c], sizeof ar->ares_result[n - 1].result_value[r]); r++; ar->ares_result[n - 1].result_props = r; } prevstate = state; state = 9; break; } } /* error out on non-terminal states */ if (state == 4 || state == 7 || state == 10 || state == 11 || state == 12) return -1; if (n > 1) { if (ares_dedup(ar, n - 1)) n--; } ar->ares_count = n; return 0; } #ifdef ARTEST /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** EX_USAGE or EX_OK */ # define NTOKENS 256 int main(int argc, char **argv) { int c; int d; int status; char *p; char *progname; struct authres ar; u_char buf[1024]; u_char *toks[NTOKENS]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; if (argc != 2) { printf("%s: usage: %s header-value\n", progname, progname); return EX_USAGE; } c = ares_tokenize(argv[1], buf, sizeof buf, toks, NTOKENS); for (d = 0; d < c; d++) printf("token %d = '%s'\n", d, toks[d]); printf("\n"); status = ares_parse(argv[1], &ar); if (status == -1) { printf("%s: ares_parse() returned -1\n", progname); return EX_OK; } printf("%d result%s found\n", ar.ares_count, ar.ares_count == 1 ? "" : "s"); printf("authserv-id '%s'\n", ar.ares_host); printf("version '%s'\n", ar.ares_version); for (c = 0; c < ar.ares_count; c++) { printf("result #%d, %d propert%s\n", c, ar.ares_result[c].result_props, ar.ares_result[c].result_props == 1 ? "y" : "ies"); printf("\tmethod \"%s\"\n", ares_xconvert(methods, ar.ares_result[c].result_method)); printf("\tresult \"%s\"\n", ares_xconvert(aresults, ar.ares_result[c].result_result)); printf("\treason \"%s\"\n", ar.ares_result[c].result_reason); for (d = 0; d < ar.ares_result[c].result_props; d++) { printf("\tproperty #%d\n", d); printf("\t\tptype \"%s\"\n", ares_xconvert(ptypes, ar.ares_result[c].result_ptype[d])); printf("\t\tproperty \"%s\"\n", ar.ares_result[c].result_property[d]); printf("\t\tvalue \"%s\"\n", ar.ares_result[c].result_value[d]); } } } #endif /* ARTEST */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-ar.h000066400000000000000000000051501337314105200226430ustar00rootroot00000000000000/* ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012-2014, The Trusted Domain Project. ** All rights reserved. ** */ #ifndef _OPENDKIM_AR_H_ #define _OPENDKIM_AR_H_ /* system includes */ #include /* opendkim includes */ #include "opendkim.h" /* limits */ #define MAXARESULTS 16 #define MAXPROPS 16 #define MAXAVALUE 256 /* ARES_METHOD_T -- type for specifying an authentication method */ typedef int ares_method_t; #define ARES_METHOD_UNKNOWN (-1) #define ARES_METHOD_AUTH 0 #define ARES_METHOD_DKIM 1 #define ARES_METHOD_DOMAINKEYS 2 #define ARES_METHOD_SENDERID 3 #define ARES_METHOD_SPF 4 #define ARES_METHOD_DKIMADSP 5 #define ARES_METHOD_IPREV 6 #define ARES_METHOD_DKIMATPS 7 #define ARES_METHOD_DMARC 8 #define ARES_METHOD_SMIME 9 #define ARES_METHOD_RRVS 10 /* ARES_RESULT_T -- type for specifying an authentication result */ typedef int ares_result_t; #define ARES_RESULT_UNDEFINED (-1) #define ARES_RESULT_PASS 0 #define ARES_RESULT_UNASSIGNED 1 /* UNASSIGNED */ #define ARES_RESULT_SOFTFAIL 2 #define ARES_RESULT_NEUTRAL 3 #define ARES_RESULT_TEMPERROR 4 #define ARES_RESULT_PERMERROR 5 #define ARES_RESULT_NONE 6 #define ARES_RESULT_FAIL 7 #define ARES_RESULT_POLICY 8 #define ARES_RESULT_NXDOMAIN 9 #define ARES_RESULT_SIGNED 10 #define ARES_RESULT_UNKNOWN 11 #define ARES_RESULT_DISCARD 12 /* ARES_PTYPE_T -- type for specifying an authentication property */ typedef int ares_ptype_t; #define ARES_PTYPE_UNKNOWN (-1) #define ARES_PTYPE_SMTP 0 #define ARES_PTYPE_HEADER 1 #define ARES_PTYPE_BODY 2 #define ARES_PTYPE_POLICY 3 /* RESULT structure -- a single result */ struct result { int result_props; ares_method_t result_method; ares_result_t result_result; ares_ptype_t result_ptype[MAXPROPS]; unsigned char result_reason[MAXAVALUE + 1]; unsigned char result_property[MAXPROPS][MAXAVALUE + 1]; unsigned char result_value[MAXPROPS][MAXAVALUE + 1]; }; /* AUTHRES structure -- the entire header parsed */ struct authres { int ares_count; unsigned char ares_host[DKIM_MAXHOSTNAMELEN + 1]; unsigned char ares_version[MAXAVALUE + 1]; struct result ares_result[MAXARESULTS]; }; /* ** ARES_PARSE -- parse an Authentication-Results: header, return a ** structure containing a parsed result ** ** Parameters: ** hdr -- NULL-terminated contents of an Authentication-Results: ** header field ** ar -- a pointer to a (struct authres) loaded by values after parsing ** ** Return value: ** 0 on success, -1 on failure. */ extern int ares_parse __P((u_char *hdr, struct authres *ar)); #endif /* _OPENDKIM_AR_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-arf.c000066400000000000000000000027031337314105200230050ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, The Trusted Domain Project. ** All rights reserved. ** */ /* system includes */ #include #include #include #include #include /* opendkim includes */ #include "opendkim-arf.h" /* ** ARF_TYPE_STRING -- translate an ARF_TYPE_* constant to a string ** ** Parameters: ** type -- an ARF_TYPE_* constant ** ** Return value: ** A string describing the "type" provided. */ char * arf_type_string(int type) { switch (type) { case ARF_TYPE_ABUSE: return "abuse"; case ARF_TYPE_FRAUD: return "fraud"; case ARF_TYPE_VIRUS: return "virus"; case ARF_TYPE_AUTHFAIL: return "auth-failure"; case ARF_TYPE_UNKNOWN: case ARF_TYPE_OTHER: default: return "other"; } } /* ** ARF_DKIM_FAILURE_STRING -- return an appropriate DKIM-Failure: string for ** an ARF report ** ** Parameters: ** ftype -- failure type, i.e. an ARF_DKIMF_* constant ** ** Return value: ** A string describing the "ftype" provided. */ char * arf_dkim_failure_string(int ftype) { switch (ftype) { case ARF_DKIMF_BODYHASH: return "bodyhash"; case ARF_DKIMF_REVOKED: return "revoked"; case ARF_DKIMF_SIGNATURE: return "signature"; case ARF_DKIMF_SYNTAX: return "syntax"; case ARF_DKIMF_OTHER: default: return "other"; } } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-arf.h000066400000000000000000000023111337314105200230050ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2011, 2012, 2014, The Trusted Domain Project. ** All rights reserved. ** */ #ifndef _DKIM_ARF_H_ #define _DKIM_ARF_H_ /* system includes */ #include #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ #define ARF_VERSION "0.1" #define ARF_TYPE_UNKNOWN (-1) #define ARF_TYPE_ABUSE 0 #define ARF_TYPE_FRAUD 1 #define ARF_TYPE_VIRUS 2 #define ARF_TYPE_AUTHFAIL 3 #define ARF_TYPE_OTHER 4 #define ARF_DKIMF_UNKNOWN (-1) #define ARF_DKIMF_BODYHASH 0 #define ARF_DKIMF_REVOKED 1 #define ARF_DKIMF_SIGNATURE 2 #define ARF_DKIMF_SYNTAX 3 #define ARF_DKIMF_OTHER 4 #define ARF_FORMAT_ARF "arf" #define ARF_OPTIONS_DKIM_ALL "all" #define ARF_OPTIONS_DKIM_DNS "d" #define ARF_OPTIONS_DKIM_OTHER "o" #define ARF_OPTIONS_DKIM_POLICY "p" #define ARF_OPTIONS_DKIM_SYNTAX "s" #define ARF_OPTIONS_DKIM_VERIFY "v" #define ARF_OPTIONS_DKIM_EXPIRED "x" /* prototypes */ extern char *arf_dkim_failure_string __P((int)); extern char *arf_type_string __P((int)); #endif /* _DKIM_ARF_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-atpszone.8.in000066400000000000000000000061321337314105200244320ustar00rootroot00000000000000.TH opendkim-atpszone 8 "The Trusted Domain Project" .SH NAME .B opendkim-atpszone \- DKIM ATPS zone file generation tool .SH SYNOPSIS .B opendkim-atpszone [\-A] [\-C address] [\-E secs] [\-h hash] [\-N ns[,...]] [\-o file] [\-r secs] [\-R secs] [\-S] [\-t secs] [\-T secs] [\-u domain] [\-v] [dataset] .SH DESCRIPTION .B opendkim-atpszone generates a file suitable for use with .I named(8) to publish a set of domains authorized as third-party signers for a local domain. The .I dataset parameter should specify a set of data as described in the .I opendkim(8) man page. It can currently refer to flat files, Sleepycat databases, comma-separated lists, LDAP directories or SQL databases. The keys in the named database are assumed to comprise a set of domains that are to be advertised using the experimental Authorized Third-Party Signers protocol as permitted to sign mail using DKIM on behalf of the local domain. Values in the database are not used. .SH OPTIONS .TP .I \-A Adds a "._atps" suffix to records in the zone file. .TP .I \-C contact Uses .I contact as the contact information to be used when an SOA record is generated (see .I \-S below). If not specified, the userid of the executing user and the local hostname will be used; if the executing user can't be determined, "hostmaster" will be used. .TP .I \-E secs When generating an SOA record (see .I \-S below), use .I secs as the default record expiration time. The default is 604800. .TP .I \-h hash Specifies which SHA hash algorithm to use. Must be one of "none", "sha1" and "sha256", with "sha256" being the default if it is available. .TP .I \-N nslist Specifies a comma-separated list of nameservers, which will be output in NS records before the TXT records. The first nameserver in this list will also be used in the SOA record (if .I \-S is also specified) as the authority hostname. .TP .I \-o file Sends output to the named .I file rather than standard output. .TP .I \-r secs When generating an SOA record (see .I \-S below), use .I secs as the zone refresh time. The default is 10800. .TP .I \-R secs When generating an SOA record (see .I \-S below), use .I secs as the zone retry time. The default is 1800. .TP .I \-S Asks for an SOA record to be generated at the top of the output. The content of this output can be controlled using the .I \-E, .I \-r, .I \-R, .I \-T options. The serial number will be generated based on the current time of day. .TP .I \-t ttl Puts a TTL (time-to-live) value of .I ttl on all records output. The units are in seconds. .TP .I \-T secs When generating an SOA record (see .I \-S below), use .I secs as the default record TTL time. The default is 86400. .TP .I \-u domain Produce output suitable for use as input to .B nsupdate(8) to add ATPS records to the named .I domain. .TP .I \-v Increases the verbosity of debugging output written to standard error. .SH VERSION This man page covers the version of .I opendkim-atpszone that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I nsupdate(8), .I opendkim(8), .I opendkim.conf(5) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-atpszone.c000066400000000000000000000246751337314105200241140ustar00rootroot00000000000000/* ** Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. ** */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* openssl includes */ #ifdef USE_GNUTLS # include # include # include # include #else /* USE_GNUTLS */ # include # include # include # include #endif /* USE_GNUTLS */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifndef SHA_DIGEST_LENGTH # define SHA_DIGEST_LENGTH 20 #endif /* ! SHA_DIGEST_LENGTH */ #ifndef SHA256_DIGEST_LENGTH # define SHA256_DIGEST_LENGTH 32 #endif /* ! SHA256_DIGEST_LENGTH */ /* libopendkim includes */ #include /* opendkim includes */ #include "opendkim-db.h" #include "util.h" #include "config.h" #include "opendkim-config.h" /* definitions */ #define ATPSZONE "._atps" #define BASE32_LENGTH 32 #define BUFRSZ 256 #define CMDLINEOPTS "AC:E:h:o:N:r:R:St:T:u:v" #define DEFEXPIRE 604800 #define DEFREFRESH 10800 #define DEFRETRY 1800 #define DEFTTL 86400 #define HOSTMASTER "hostmaster" #define MAXNS 16 #define VALIDATPS "v=ATPS1" /* globals */ char *progname; /* ** USAGE -- print usage message and exit ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [opts] [dataset]\n" "\t-A \tinclude '._atps' suffix\n" "\t-C user@host\tcontact address to include in SOA\n" "\t-E secs \tuse specified expiration time in SOA\n" "\t-h hash \thash algorithm\n" "\t-o file \toutput file\n" "\t-N ns[,...] \tlist NS records\n" "\t-r secs \tuse specified refresh time in SOA\n" "\t-R secs \tuse specified retry time in SOA\n" "\t-S \twrite an SOA record\n" "\t-t secs \tuse specified per-record TTL\n" "\t-T secs \tuse specified default TTL in SOA\n" "\t-u domain \tproduce nsupdate(8) script\n" "\t-v \tverbose output\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { _Bool suffix = FALSE; _Bool writesoa = FALSE; _Bool nsupdate = FALSE; int c; int status; int verbose = 0; int ttl = -1; int defttl = DEFTTL; int expire = DEFEXPIRE; int refresh = DEFREFRESH; int retry = DEFRETRY; int nscount = 0; time_t now; size_t dlen; size_t b32len; size_t shalen; char *p; char *dataset = NULL; char *udomain = NULL; char *outfile = NULL; char *hash = NULL; char *contact = NULL; char *nameservers = NULL; char *nslist[MAXNS]; FILE *out; DKIMF_DB db; #ifdef USE_GNUTLS gnutls_hash_hd_t sha; #else /* USE_GNUTLS */ SHA_CTX sha; # ifdef HAVE_SHA256 SHA256_CTX sha256; # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ char domain[DKIM_MAXHOSTNAMELEN + 1]; char hostname[DKIM_MAXHOSTNAMELEN + 1]; #ifdef HAVE_SHA256 char shaout[SHA256_DIGEST_LENGTH]; #else /* HAVE_SHA256 */ char shaout[SHA_DIGEST_LENGTH]; #endif /* HAVE_SHA256 */ char base32[BASE32_LENGTH + 1]; char value[BUFRSZ + 1]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) { switch (c) { case 'A': suffix = TRUE; break; case 'C': contact = strdup(optarg); break; case 'E': expire = strtol(optarg, &p, 10); if (*p != '\0' || expire < 0) { fprintf(stderr, "%s: invalid expire value\n", progname); return EX_USAGE; } break; case 'h': if (strcasecmp(optarg, "sha1") != 0 && strcasecmp(optarg, "sha256") != 0 && strcasecmp(optarg, "none") != 0) { fprintf(stderr, "%s: invalid hash algorithm\n", progname); return EX_USAGE; } #ifndef HAVE_SHA256 else if (strcasecmp(optarg, "sha256") == 0) { fprintf(stderr, "%s: hash algorithm \"%s\" not supported\n", progname, optarg); return EX_SOFTWARE; } #endif /* ! HAVE_SHA256 */ hash = optarg; if (strcasecmp(hash, "sha1") == 0) shalen = SHA_DIGEST_LENGTH; else shalen = SHA256_DIGEST_LENGTH; break; case 'N': nameservers = strdup(optarg); break; case 'o': outfile = optarg; break; case 'r': refresh = strtol(optarg, &p, 10); if (*p != '\0' || refresh < 0) { fprintf(stderr, "%s: invalid refresh value\n", progname); return EX_USAGE; } break; case 'R': retry = strtol(optarg, &p, 10); if (*p != '\0' || retry < 0) { fprintf(stderr, "%s: invalid retry value\n", progname); return EX_USAGE; } break; case 'S': writesoa = TRUE; break; case 't': ttl = strtol(optarg, &p, 10); if (*p != '\0' || ttl < 0) { fprintf(stderr, "%s: invalid TTL value\n", progname); return EX_USAGE; } break; case 'T': defttl = strtol(optarg, &p, 10); if (*p != '\0' || defttl < 0) { fprintf(stderr, "%s: invalid default TTL value\n", progname); return EX_USAGE; } break; case 'u': nsupdate = TRUE; udomain = optarg; break; case 'v': verbose++; break; default: return usage(); } } if (optind != argc) dataset = argv[optind]; status = dkimf_db_open(&db, dataset, DKIMF_DB_FLAG_READONLY, NULL, NULL); if (status != 0) { fprintf(stderr, "%s: dkimf_db_open() failed\n", progname); return 1; } if (dkimf_db_type(db) == DKIMF_DB_TYPE_REFILE) { fprintf(stderr, "%s: invalid data set type\n", progname); (void) dkimf_db_close(db); return 1; } if (verbose > 0) fprintf(stderr, "%s: database opened\n", progname); if (outfile != NULL) { out = fopen(outfile, "w"); if (out == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, outfile, strerror(errno)); (void) dkimf_db_close(db); return 1; } } else { out = stdout; } if (nameservers != NULL) { for (p = strtok(nameservers, ","); p != NULL && nscount < MAXNS; p = strtok(NULL, ",")) nslist[nscount++] = p; } memset(hostname, '\0', sizeof hostname); gethostname(hostname, sizeof hostname); if (nscount == 0) nslist[nscount++] = hostname; (void) time(&now); if (!nsupdate) { fprintf(out, "; DKIM ATPS zone data\n"); fprintf(out, "; auto-generated by %s at %s\n", progname, ctime(&now)); } if (writesoa && !nsupdate) { struct tm *tm; fprintf(out, "@\tIN\tSOA\t%s\t", nslist[0]); if (contact != NULL) { for (p = contact; *p != '\0'; p++) { if (*p == '@') *p = '.'; } fprintf(out, "%s", contact); } else { struct passwd *pwd; pwd = getpwuid(getuid()); fprintf(out, "%s.%s", pwd == NULL ? HOSTMASTER : pwd->pw_name, hostname); } tm = localtime(&now); fprintf(out, "\t (\n" "\t%04d%02d%02d%02d ; Serial (yyyymmddhh)\n" "\t%-10d ; Refresh\n" "\t%-10d ; Retry\n" "\t%-10d ; Expire\n" "\t%-10d ) ; Default\n\n", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, refresh, retry, expire, defttl); } if (nameservers != NULL && !nsupdate) { for (c = 0; c < nscount; c++) fprintf(out, "\tIN\tNS\t%s\n", nslist[c]); fprintf(out, "\n"); } if (nsupdate) { fprintf(out, "server %s\n", nslist[0]); fprintf(out, "zone %s\n", udomain); } #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ for (c = 0; ; c++) { memset(domain, '\0', sizeof domain); dlen = sizeof domain; status = dkimf_db_walk(db, c == 0, domain, &dlen, NULL, 0); if (status == -1) { fprintf(stderr, "%s: dkimf_db_walk(%d) failed\n", progname, c); (void) dkimf_db_close(db); return 1; } else if (status == 1) { break; } /* convert to lowercase */ dkimf_lowercase(domain); memset(base32, '\0', sizeof base32); if (hash == NULL || strcasecmp(hash, "none") != 0) { /* compute SHA1 hash */ #ifdef USE_GNUTLS # ifdef HAVE_SHA256 if (hash == NULL || strcasecmp(hash, "sha256") == 0) { (void) gnutls_hash_init(&sha, GNUTLS_DIG_SHA256); } else { (void) gnutls_hash_init(&sha, GNUTLS_DIG_SHA1); } # else /* HAVE_SHA256 */ (void) gnutls_hash_init(&sha, GNUTLS_DIG_SHA1); # endif /* HAVE_SHA256 */ (void) gnutls_hash(sha, domain, strlen(domain)); (void) gnutls_hash_deinit(sha, shaout); #else /* USE_GNUTLS */ # ifdef HAVE_SHA256 if (hash == NULL || strcasecmp(hash, "sha256") == 0) { SHA256_Init(&sha256); SHA256_Update(&sha256, domain, strlen(domain)); SHA256_Final(shaout, &sha256); } else { SHA1_Init(&sha); SHA1_Update(&sha, domain, strlen(domain)); SHA1_Final(shaout, &sha); } # else /* HAVE_SHA256 */ SHA1_Init(&sha); SHA1_Update(&sha, domain, strlen(domain)); SHA1_Final(shaout, &sha); # endif /* HAVE_SHA256 */ #endif /* USE_GNUTLS */ /* encode with base32 */ memset(base32, '\0', sizeof base32); b32len = sizeof base32 - 1; (void) dkim_base32_encode(base32, &b32len, shaout, shalen); } /* generate output */ snprintf(value, sizeof value, "%s; d=%s", VALIDATPS, domain); if (nsupdate) { fprintf(out, "update add %s%s TXT %d \"%s\"\n", base32[0] == '\0' ? domain : base32, suffix ? ATPSZONE : "", ttl == -1 ? defttl : ttl, value); } else if (ttl == -1) { fprintf(out, "%s%s\tIN\tTXT\t\"%s\"\n", base32[0] == '\0' ? domain : base32, suffix ? ATPSZONE : "", value); } else { fprintf(out, "%s%s\t%d\tIN\tTXT\t\"%s\"\n", base32[0] == '\0' ? domain : base32, suffix ? ATPSZONE : "", ttl, value); } } (void) dkimf_db_close(db); if (nsupdate) fprintf(out, "send\nanswer\n"); if (out != stdout) fclose(out); if (verbose > 0) { fprintf(stdout, "%s: %d record%s written\n", progname, c, c == 1 ? "" : "s"); } return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-config.h000066400000000000000000000241071337314105200235110ustar00rootroot00000000000000/* ** Copyright (c) 2006-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ #ifndef _DKIM_CONFIG_H_ #define _DKIM_CONFIG_H_ #include "build-config.h" /* system includes */ #include /* macros */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* config definition */ struct configdef dkimf_config[] = { { "AllowSHA1Only", CONFIG_TYPE_BOOLEAN, FALSE }, { "AlwaysAddARHeader", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef _FFR_ATPS { "ATPSDomains", CONFIG_TYPE_STRING, FALSE }, { "ATPSHashAlgorithm", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_ATPS */ { "AuthservID", CONFIG_TYPE_STRING, FALSE }, { "AuthservIDWithJobID", CONFIG_TYPE_BOOLEAN, FALSE }, { "AutoRestart", CONFIG_TYPE_BOOLEAN, FALSE }, { "AutoRestartCount", CONFIG_TYPE_INTEGER, FALSE }, { "AutoRestartRate", CONFIG_TYPE_STRING, FALSE }, { "Background", CONFIG_TYPE_BOOLEAN, FALSE }, { "BaseDirectory", CONFIG_TYPE_STRING, FALSE }, { "BodyLengthDB", CONFIG_TYPE_STRING, FALSE }, #ifdef USE_UNBOUND { "BogusKey", CONFIG_TYPE_STRING, FALSE }, #endif /* USE_UNBOUND*/ { "Canonicalization", CONFIG_TYPE_STRING, FALSE }, { "CaptureUnknownErrors", CONFIG_TYPE_BOOLEAN, FALSE }, { "ChangeRootDirectory", CONFIG_TYPE_STRING, FALSE }, { "ClockDrift", CONFIG_TYPE_INTEGER, FALSE }, #ifdef _FFR_CONDITIONAL { "ConditionalSignatures", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_DEFAULT_SENDER { "DefaultSender", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_DEFAULT_SENDER */ { "Diagnostics", CONFIG_TYPE_BOOLEAN, FALSE }, { "DiagnosticDirectory", CONFIG_TYPE_STRING, FALSE }, { "DisableCryptoInit", CONFIG_TYPE_BOOLEAN, FALSE }, { "DNSConnect", CONFIG_TYPE_BOOLEAN, FALSE }, { "DNSTimeout", CONFIG_TYPE_INTEGER, FALSE }, { "Domain", CONFIG_TYPE_STRING, FALSE }, { "DomainKeysCompat", CONFIG_TYPE_BOOLEAN, FALSE }, { "DontSignMailTo", CONFIG_TYPE_STRING, FALSE }, { "EnableCoredumps", CONFIG_TYPE_BOOLEAN, FALSE }, { "ExemptDomains", CONFIG_TYPE_STRING, FALSE }, { "ExternalIgnoreList", CONFIG_TYPE_STRING, FALSE }, #ifdef USE_LUA { "FinalPolicyScript", CONFIG_TYPE_STRING, FALSE }, #endif /* USE_LUA */ { "FixCRLF", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef _FFR_RATE_LIMIT { "FlowData", CONFIG_TYPE_STRING, FALSE }, { "FlowDataFactor", CONFIG_TYPE_INTEGER, FALSE }, { "FlowDataTTL", CONFIG_TYPE_INTEGER, FALSE }, #endif /* _FFR_RATE_LIMIT */ #ifdef _FFR_IDENTITY_HEADER { "IdentityHeader", CONFIG_TYPE_STRING, FALSE }, { "IdentityHeaderRemove", CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* _FFR_IDENTITY_HEADER */ { "IgnoreMalformedMail", CONFIG_TYPE_BOOLEAN, FALSE }, { "Include", CONFIG_TYPE_INCLUDE, FALSE }, { "InternalHosts", CONFIG_TYPE_STRING, FALSE }, { "KeepAuthResults", CONFIG_TYPE_BOOLEAN, FALSE }, { "KeepTemporaryFiles", CONFIG_TYPE_BOOLEAN, FALSE }, { "KeyFile", CONFIG_TYPE_STRING, FALSE }, { "KeyTable", CONFIG_TYPE_STRING, FALSE }, #ifdef USE_LDAP { "LDAPAuthMechanism", CONFIG_TYPE_STRING, FALSE }, # ifdef USE_SASL { "LDAPAuthName", CONFIG_TYPE_STRING, FALSE }, { "LDAPAuthRealm", CONFIG_TYPE_STRING, FALSE }, { "LDAPAuthUser", CONFIG_TYPE_STRING, FALSE }, # endif /* USE_SASL */ { "LDAPBindPassword", CONFIG_TYPE_STRING, FALSE }, { "LDAPBindUser", CONFIG_TYPE_STRING, FALSE }, { "LDAPDisableCache", CONFIG_TYPE_BOOLEAN, FALSE }, { "LDAPKeepaliveIdle", CONFIG_TYPE_STRING, FALSE }, { "LDAPKeepaliveInterval", CONFIG_TYPE_STRING, FALSE }, { "LDAPKeepaliveProbes", CONFIG_TYPE_STRING, FALSE }, { "LDAPTimeout", CONFIG_TYPE_STRING, FALSE }, { "LDAPUseTLS", CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* USE_LDAP */ { "LogResults", CONFIG_TYPE_BOOLEAN, FALSE }, { "LogWhy", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef _FFR_LUA_ONLY_SIGNING { "LuaOnlySigning", CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* _FFR_LUA_ONLY_SIGNING */ { "MaximumHeaders", CONFIG_TYPE_INTEGER, FALSE }, { "MaximumSignedBytes", CONFIG_TYPE_INTEGER, FALSE }, { "MaximumSignaturesToVerify", CONFIG_TYPE_INTEGER, FALSE }, { "MacroList", CONFIG_TYPE_STRING, FALSE }, { "MilterDebug", CONFIG_TYPE_INTEGER, FALSE }, { "Minimum", CONFIG_TYPE_STRING, FALSE }, { "MinimumKeyBits", CONFIG_TYPE_INTEGER, FALSE }, { "MultipleSignatures", CONFIG_TYPE_BOOLEAN, FALSE }, { "Mode", CONFIG_TYPE_STRING, FALSE }, { "MTA", CONFIG_TYPE_STRING, FALSE }, { "MTACommand", CONFIG_TYPE_STRING, FALSE }, { "MustBeSigned", CONFIG_TYPE_STRING, FALSE }, { "Nameservers", CONFIG_TYPE_STRING, FALSE }, { "NoHeaderB", CONFIG_TYPE_BOOLEAN, FALSE }, { "OmitHeaders", CONFIG_TYPE_STRING, FALSE }, { "On-BadSignature", CONFIG_TYPE_STRING, FALSE }, { "On-Default", CONFIG_TYPE_STRING, FALSE }, { "On-DNSError", CONFIG_TYPE_STRING, FALSE }, { "On-InternalError", CONFIG_TYPE_STRING, FALSE }, { "On-KeyNotFound", CONFIG_TYPE_STRING, FALSE }, { "On-NoSignature", CONFIG_TYPE_STRING, FALSE }, #ifdef _FFR_REPUTATION { "On-ReputationError", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_REPUTATION */ { "On-Security", CONFIG_TYPE_STRING, FALSE }, { "On-SignatureError", CONFIG_TYPE_STRING, FALSE }, { "OverSignHeaders", CONFIG_TYPE_STRING, FALSE }, { "PeerList", CONFIG_TYPE_STRING, FALSE }, { "PidFile", CONFIG_TYPE_STRING, FALSE }, #ifdef POPAUTH { "POPDBFile", CONFIG_TYPE_STRING, FALSE }, #endif /* POPAUTH */ { "Quarantine", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef QUERY_CACHE { "QueryCache", CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* QUERY_CACHE */ #ifdef _FFR_RATE_LIMIT { "RateLimits", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_RATE_LIMIT */ { "RedirectFailuresTo", CONFIG_TYPE_STRING, FALSE }, { "RemoveARAll", CONFIG_TYPE_BOOLEAN, FALSE }, { "RemoveARFrom", CONFIG_TYPE_STRING, FALSE }, { "RemoveOldSignatures", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef _FFR_REPLACE_RULES { "ReplaceRules", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_REPLACE_RULES */ { "ReportAddress", CONFIG_TYPE_STRING, FALSE }, { "ReportBccAddress", CONFIG_TYPE_STRING, FALSE }, #ifdef _FFR_REPUTATION { "ReputationCache", CONFIG_TYPE_STRING, FALSE }, { "ReputationCacheTTL", CONFIG_TYPE_INTEGER, FALSE }, { "ReputationDuplicates", CONFIG_TYPE_STRING, FALSE }, { "ReputationLimits", CONFIG_TYPE_STRING, FALSE }, { "ReputationLowTime", CONFIG_TYPE_STRING, FALSE }, { "ReputationMinimum", CONFIG_TYPE_INTEGER, FALSE }, { "ReputationLimitModifiers", CONFIG_TYPE_STRING, FALSE }, { "ReputationRatios", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_REPUTATION */ #ifdef _FFR_REPRRD { "ReputationRRDHashDepth", CONFIG_TYPE_INTEGER, FALSE }, { "ReputationRRDRoot", CONFIG_TYPE_STRING, FALSE }, { "ReputationTest", /* DUP */ CONFIG_TYPE_BOOLEAN, FALSE }, { "ReputationVerbose", /* DUP */ CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* _FFR_REPRRD */ #ifdef _FFR_REPUTATION { "ReputationSpamCheck", CONFIG_TYPE_STRING, FALSE }, { "ReputationTest", /* DUP */ CONFIG_TYPE_BOOLEAN, FALSE }, { "ReputationTimeFactor", CONFIG_TYPE_INTEGER, FALSE }, { "ReputationTimeout", CONFIG_TYPE_INTEGER, FALSE }, { "ReputationVerbose", /* DUP */ CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* _FFR_REPUTATION */ { "RequestReports", CONFIG_TYPE_BOOLEAN, FALSE }, { "RequiredHeaders", CONFIG_TYPE_BOOLEAN, FALSE }, { "RequireSafeKeys", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef _FFR_RESIGN { "ResignAll", CONFIG_TYPE_BOOLEAN, FALSE }, { "ResignMailTo", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_RESIGN */ { "ResolverConfiguration", CONFIG_TYPE_STRING, FALSE }, { "ResolverTracing", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef USE_LUA { "ScreenPolicyScript", CONFIG_TYPE_STRING, FALSE }, #endif /* USE_LUA */ { "Selector", CONFIG_TYPE_STRING, FALSE }, { "SelectCanonicalizationHeader", CONFIG_TYPE_STRING, FALSE }, { "SenderHeaders", CONFIG_TYPE_STRING, FALSE }, #ifdef _FFR_SENDER_MACRO { "SenderMacro", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_SENDER_MACRO */ { "SendReports", CONFIG_TYPE_BOOLEAN, FALSE }, #ifdef USE_LUA { "SetupPolicyScript", CONFIG_TYPE_STRING, FALSE }, #endif /* USE_LUA */ { "SignatureAlgorithm", CONFIG_TYPE_STRING, FALSE }, { "SignatureTTL", CONFIG_TYPE_INTEGER, FALSE }, { "SignHeaders", CONFIG_TYPE_STRING, FALSE }, { "SigningTable", CONFIG_TYPE_STRING, FALSE }, #ifdef HAVE_CURL_EASY_STRERROR { "SMTPURI", CONFIG_TYPE_STRING, FALSE }, #endif /* HAVE_CURL_EASY_STRERROR */ { "Socket", CONFIG_TYPE_STRING, FALSE }, { "SoftwareHeader", CONFIG_TYPE_BOOLEAN, FALSE }, #if defined(USE_ODBX) || defined(USE_LDAP) { "SoftStart", CONFIG_TYPE_BOOLEAN, FALSE }, #endif /* defined(USE_ODBX) || defined(USE_LDAP) */ #ifdef _FFR_STATS { "Statistics", CONFIG_TYPE_STRING, FALSE }, { "StatisticsName", CONFIG_TYPE_STRING, FALSE }, # ifdef USE_LUA # ifdef _FFR_STATSEXT { "StatisticsPolicyScript", CONFIG_TYPE_STRING, FALSE }, # endif /* _FFR_STATSEXT */ # endif /* USE_LUA */ { "StatisticsPrefix", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_STATS */ { "StrictHeaders", CONFIG_TYPE_BOOLEAN, FALSE }, { "StrictTestMode", CONFIG_TYPE_BOOLEAN, FALSE }, { "SubDomains", CONFIG_TYPE_BOOLEAN, FALSE }, { "Syslog", CONFIG_TYPE_BOOLEAN, FALSE }, { "SyslogFacility", CONFIG_TYPE_STRING, FALSE }, { "SyslogName", CONFIG_TYPE_STRING, FALSE }, { "SyslogSuccess", CONFIG_TYPE_BOOLEAN, FALSE }, { "TemporaryDirectory", CONFIG_TYPE_STRING, FALSE }, { "TestDNSData", CONFIG_TYPE_STRING, FALSE }, { "TestPublicKeys", CONFIG_TYPE_STRING, FALSE }, { "TrustAnchorFile", CONFIG_TYPE_STRING, FALSE }, { "TrustSignaturesFrom", CONFIG_TYPE_STRING, FALSE }, { "UMask", CONFIG_TYPE_INTEGER, FALSE }, #ifdef USE_UNBOUND { "UnprotectedKey", CONFIG_TYPE_STRING, FALSE }, #endif /* USE_UNBOUND */ { "UserID", CONFIG_TYPE_STRING, FALSE }, #ifdef _FFR_VBR { "VBR-Certifiers", CONFIG_TYPE_STRING, FALSE }, { "VBR-PurgeFields", CONFIG_TYPE_BOOLEAN, FALSE }, { "VBR-TrustedCertifiers", CONFIG_TYPE_STRING, FALSE }, { "VBR-TrustedCertifiersOnly", CONFIG_TYPE_BOOLEAN, FALSE }, { "VBR-Type", CONFIG_TYPE_STRING, FALSE }, #endif /* _FFR_VBR */ { "WeakSyntaxChecks", CONFIG_TYPE_BOOLEAN, FALSE }, { "X-Header", CONFIG_TYPE_BOOLEAN, FALSE }, { NULL, (u_int) -1, FALSE } }; #endif /* _DKIM_CONFIG_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-crypto.c000066400000000000000000000200111337314105200235450ustar00rootroot00000000000000/* ** Copyright (c) 2008, 2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012, 2013, 2018, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #ifdef USE_GNUTLS /* libgnutls includes */ # include #else /* USE_GNUTLS */ /* openssl includes */ # include # include # include # include # include #endif /* USE_GNUTLS */ /* opendkim includes */ #include "opendkim-crypto.h" #include "opendkim.h" /* globals */ static _Bool crypto_init_done = FALSE; #ifdef USE_GNUTLS static pthread_key_t logkey; /* ** DKIMF_CRYPTO_LOG -- log something from inside GnuTLS ** ** Parameters: ** sev -- log level ** str -- string to log ** ** Return value: ** None. */ static void dkimf_crypto_log(int sev, const char *str) { char *buf; buf = pthread_getspecific(logkey); if (buf == NULL) { buf = malloc(BUFRSZ); pthread_setspecific(logkey, buf); } if (buf != NULL) snprintf(buf, BUFRSZ, "%s", str); } /* ** DKIMF_CRYPTO_GETERROR -- return any logged error ** ** Parameters: ** None. ** ** Return value: ** Pointer to the most recently logged error, or NULL if none. */ const char * dkimf_crypto_geterror(void) { return (const char *) pthread_getspecific(logkey); } /* ** DKIMF_CRYPTO_INIT -- set up GnuTLS dependencies ** ** Parameters: ** None. ** ** Return value: ** 0 -- success ** !0 -- an error code (a la errno) */ int dkimf_crypto_init(void) { (void) gnutls_global_set_log_function(dkimf_crypto_log); (void) gnutls_global_init(); (void) pthread_key_create(&logkey, free); return 0; } /* ** DKIMF_CRYPTO_FREE -- tear down libGnuTLS dependencies ** ** Parameters: ** None. ** ** Return value: ** None. */ void dkimf_crypto_free(void) { if (crypto_init_done) { (void) gnutls_global_deinit(); (void) pthread_key_delete(logkey); } return; } #else /* USE_GNUTLS */ static pthread_mutex_t id_lock; static pthread_key_t id_key; static unsigned int nmutexes = 0; static unsigned long threadid = 0L; static pthread_mutex_t *mutexes = NULL; /* ** DKIMF_CRYPTO_LOCK_CALLBACK -- locking callback for libcrypto ** ** Parameters: ** mode -- lock mode (request from libcrypto) ** idx -- lock index for this request ** file -- file making the request ** line -- line making the request ** ** Return value: ** None. */ static void dkimf_crypto_lock_callback(int mode, int idx, /* UNUSED */ const char *file, /* UNUSED */ int line) { int status; if ((mode & CRYPTO_LOCK) != 0) status = pthread_mutex_lock(&mutexes[idx]); else status = pthread_mutex_unlock(&mutexes[idx]); assert(status == 0); } /* ** DKIMF_CRYPTO_GET_ID -- generate/retrieve thread ID ** ** Parameters: ** ** Return value: ** */ static unsigned long dkimf_crypto_get_id(void) { unsigned long *id; id = pthread_getspecific(id_key); if (id == NULL) { id = (unsigned long *) malloc(sizeof *id); assert(pthread_mutex_lock(&id_lock) == 0); threadid++; *id = threadid; assert(pthread_mutex_unlock(&id_lock) == 0); assert(pthread_setspecific(id_key, id) == 0); } return *id; } /* ** DKIMF_CRYPTO_FREE_ID -- destroy thread ID ** ** Parameters: ** ptr -- pointer to be destroyed ** ** Return value: ** None. */ static void dkimf_crypto_free_id(void *ptr) { /* ** Trick dkimf_crypto_get_id(); the thread-specific pointer has ** already been cleared at this point, but dkimf_crypto_get_id() ** may be called by ERR_remove_state() which will then allocate a ** new thread pointer if the thread-specific pointer is NULL. This ** means a memory leak of thread IDs and, on Solaris, an infinite loop ** because the destructor (indirectly) re-sets the thread-specific ** pointer to something not NULL. See pthread_key_create(3). */ if (ptr != NULL) { assert(pthread_setspecific(id_key, ptr) == 0); #if OPENSSL_VERSION_NUMBER >= 0x10100000 OPENSSL_thread_stop(); #else ERR_remove_state(0); #endif free(ptr); /* now we can actually clear it for real */ assert(pthread_setspecific(id_key, NULL) == 0); } } /* ** DKIMF_CRYPTO_DYN_CREATE -- dynamically create a mutex ** ** Parameters: ** file -- file making the request ** line -- line making the request ** ** Return value: ** Pointer to the new mutex. */ static struct CRYPTO_dynlock_value * dkimf_crypto_dyn_create(/* UNUSED */ const char *file, /* UNUSED */ int line) { int err; pthread_mutex_t *new; new = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); if (new == NULL) return NULL; err = pthread_mutex_init(new, NULL); if (err != 0) { free(new); return NULL; } return (void *) new; } /* ** DKIMF_CRYPTO_DYN_DESTROY -- destroy a dynamic mutex ** ** Parameters: ** mutex -- pointer to the mutex to destroy ** file -- file making the request ** line -- line making the request ** ** Return value: ** None. */ static void dkimf_crypto_dyn_destroy(struct CRYPTO_dynlock_value *lock, /* UNUSED */ const char *file, /* UNUSED */ int line) { assert(lock != NULL); pthread_mutex_destroy((pthread_mutex_t *) lock); free(lock); } /* ** DKIMF_CRYPTO_DYN_LOCK -- lock/unlock a dynamic mutex ** ** Parameters: ** mode -- lock mode (request from libcrypto) ** mutex -- pointer to the mutex to lock/unlock ** file -- file making the request ** line -- line making the request ** ** Return value: ** None. */ static void dkimf_crypto_dyn_lock(int mode, struct CRYPTO_dynlock_value *lock, /* UNUSED */ const char *file, /* UNUSED */ int line) { int status; assert(lock != NULL); if ((mode & CRYPTO_LOCK) != 0) status = pthread_mutex_lock((pthread_mutex_t *) lock); else status = pthread_mutex_unlock((pthread_mutex_t *) lock); assert(status == 0); } /* ** DKIMF_CRYPTO_INIT -- set up openssl dependencies ** ** Parameters: ** None. ** ** Return value: ** 0 -- success ** !0 -- an error code (a la errno) */ int dkimf_crypto_init(void) { int c; int n; int status; n = CRYPTO_num_locks(); mutexes = (pthread_mutex_t *) malloc(n * sizeof(pthread_mutex_t)); if (mutexes == NULL) return errno; for (c = 0; c < n; c++) { status = pthread_mutex_init(&mutexes[c], NULL); if (status != 0) return status; } status = pthread_mutex_init(&id_lock, NULL); if (status != 0) return status; nmutexes = n; status = pthread_key_create(&id_key, &dkimf_crypto_free_id); if (status != 0) return status; SSL_load_error_strings(); #if OPENSSL_VERSION_NUMBER < 0x10100000L SSL_library_init(); #else /* OPENSSL_VERSION_NUMBER < 0x10100000L */ OPENSSL_init_ssl(0, NULL); #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ ERR_load_crypto_strings(); CRYPTO_set_id_callback(&dkimf_crypto_get_id); CRYPTO_set_locking_callback(&dkimf_crypto_lock_callback); CRYPTO_set_dynlock_create_callback(&dkimf_crypto_dyn_create); CRYPTO_set_dynlock_lock_callback(&dkimf_crypto_dyn_lock); CRYPTO_set_dynlock_destroy_callback(&dkimf_crypto_dyn_destroy); #ifdef USE_OPENSSL_ENGINE if (!SSL_set_engine(NULL)) return EINVAL; #endif /* USE_OPENSSL_ENGINE */ crypto_init_done = TRUE; return 0; } /* ** DKIMF_CRYPTO_FREE -- tear down openssl dependencies ** ** Parameters: ** None. ** ** Return value: ** None. */ void dkimf_crypto_free(void) { if (crypto_init_done) { #if OPENSSL_VERSION_NUMBER >= 0x10100000 OPENSSL_thread_stop(); #else CRYPTO_cleanup_all_ex_data(); CONF_modules_free(); EVP_cleanup(); ERR_free_strings(); ERR_remove_state(0); #endif if (nmutexes > 0) { unsigned int c; for (c = 0; c < nmutexes; c++) pthread_mutex_destroy(&mutexes[c]); free(mutexes); mutexes = NULL; nmutexes = 0; } crypto_init_done = FALSE; } } #endif /* USE_GNUTLS */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-crypto.h000066400000000000000000000011521337314105200235570ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. ** */ #ifndef _DKIM_CRYPTO_H_ #define _DKIM_CRYPTO_H_ #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* PROTOTYPES */ #ifdef USE_GNUTLS extern const char *dkimf_crypto_geterror __P((void)); #endif /* USE_GNUTLS */ extern int dkimf_crypto_init __P((void)); extern void dkimf_crypto_free __P((void)); #endif /* _DKIM_CRYPTO_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-db.c000066400000000000000000004140131337314105200226230ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* ! _REENTRANT */ /* system includes */ #include #include #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #include #include #include #include #include #include /* libopendkim includes */ #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* repute includes */ #ifdef _FFR_REPUTATION # include #endif /* _FFR_REPUTATION */ /* opendkim includes */ #include "util.h" #ifdef OPENDKIM_DB_ONLY # undef USE_LDAP # undef USE_SASL # undef USE_ODBX # undef USE_LUA # undef _FFR_SOCKETDB #endif /* OPENDKIM_DB_ONLY */ #include "opendkim-db.h" #ifdef USE_LUA # include "opendkim-lua.h" #endif /* USE_LUA */ #include "opendkim.h" /* various DB library includes */ #ifdef _FFR_SOCKETDB # include # include # include # include #endif /* _FFR_SOCKETDB */ #ifdef USE_DB # include #endif /* USE_DB */ #ifdef USE_ODBX # include #endif /* USE_ODBX */ #ifdef USE_LDAP # include #endif /* USE_LDAP */ #ifdef USE_SASL # include #endif /* USE_SASL */ #ifdef USE_LUA # include #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED # include #endif /* USE_LIBMEMCACHED */ #ifdef USE_MDB # include #endif /* USE_MDB */ #ifdef USE_ERLANG # include # include # include #endif /* USE_ERLANG */ /* macros */ #define BUFRSZ 1024 #define DEFARRAYSZ 16 #ifdef _FFR_DB_HANDLE_POOLS # define DEFPOOLMAX 10 #endif /* _FFR_DB_HANDLE_POOLS */ #define DKIMF_DB_DEFASIZE 8 #define DKIMF_DB_MODE 0644 #define DKIMF_LDAP_MAXURIS 8 #define DKIMF_LDAP_DEFTIMEOUT 5 #ifdef _FFR_LDAP_CACHING # define DKIMF_LDAP_TTL 600 #endif /* _FFR_LDAP_CACHING */ #ifdef _FFR_SOCKETDB # define DKIMF_SOCKET_TIMEOUT 5 #endif /* _FFR_SOCKETDB */ #define DKIMF_DB_IFLAG_FREEARRAY 0x01 #define DKIMF_DB_IFLAG_RECONNECT 0x02 #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ! MAX */ #define STRORNULL(x) ((x)[0] == '\0' ? NULL : (x)) #ifdef USE_DB # ifndef DB_NOTFOUND # define DB_NOTFOUND 1 # endif /* ! DB_NOTFOUND */ # ifndef DB_VERSION_MAJOR # define DB_VERSION_MAJOR 1 # endif /* ! DB_VERSION_MAJOR */ # define DB_VERSION_CHECK(x,y,z) ((DB_VERSION_MAJOR == (x) && \ DB_VERSION_MINOR == (y) && \ DB_VERSION_PATCH >= (z)) || \ (DB_VERSION_MAJOR == (x) && \ DB_VERSION_MINOR > (y)) || \ DB_VERSION_MAJOR > (x)) # if DB_VERSION_CHECK(3,0,0) # define DB_STRERROR(x) db_strerror(x) # else /* DB_VERSION_CHECK(3,0,0) */ # define DB_STRERROR(x) strerror(errno) # endif /* DB_VERSION_CHECK(3,0,0) */ # if DB_VERSION_MAJOR < 2 # define DKIMF_DBCLOSE(db) (db)->close((db)) # else /* DB_VERSION_MAJOR < 2 */ # define DKIMF_DBCLOSE(db) (db)->close((db), 0) # endif /* DB_VERSION_MAJOR < 2 */ #endif /* USE_DB */ /* macros */ #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ /* data types */ struct dkimf_db { u_int db_flags; u_int db_iflags; u_int db_type; int db_status; int db_nrecs; pthread_mutex_t * db_lock; void * db_handle; /* handler handle */ void * db_data; /* dkimf_db handle */ void * db_cursor; /* cursor */ void * db_entry; /* entry (context) */ char ** db_array; }; struct dkimf_db_table { char * name; int code; }; struct dkimf_db_list { char * db_list_key; char * db_list_value; struct dkimf_db_list * db_list_next; }; struct dkimf_db_relist { regex_t db_relist_re; char * db_relist_data; struct dkimf_db_relist * db_relist_next; }; #ifdef USE_ODBX struct dkimf_db_dsn { char dsn_backend[BUFRSZ]; char dsn_datacol[BUFRSZ]; char dsn_dbase[BUFRSZ]; char dsn_host[BUFRSZ]; char dsn_keycol[BUFRSZ]; char dsn_password[BUFRSZ]; char dsn_port[BUFRSZ]; char dsn_table[BUFRSZ]; char dsn_user[BUFRSZ]; const char * dsn_filter; }; #endif /* USE_ODBX */ #ifdef USE_LDAP struct dkimf_db_ldap { int ldap_timeout; char ldap_urilist[BUFRSZ]; LDAPURLDesc * ldap_descr; # ifdef _FFR_LDAP_CACHING # ifdef USE_DB DKIMF_DB ldap_cache; # endif /* USE_DB */ # endif /* _FFR_LDAP_CACHING */ pthread_mutex_t ldap_lock; }; # ifdef _FFR_LDAP_CACHING # ifdef USE_DB # define DKIMF_DB_CACHE_DATA 0 # define DKIMF_DB_CACHE_PENDING 1 struct dkimf_db_ldap_cache { _Bool ldc_absent; int ldc_state; int ldc_nresults; int ldc_waiters; int ldc_error; time_t ldc_expire; void * ldc_handle; char ** ldc_results; pthread_cond_t ldc_cond; }; # endif /* USE_DB */ # endif /* _FFR_LDAP_CACHING */ #endif /* USE_LDAP */ #ifdef USE_LUA struct dkimf_db_lua { char * lua_script; size_t lua_scriptlen; char * lua_error; }; #endif /* USE_LUA */ #ifdef _FFR_SOCKETDB struct dkimf_db_socket { int sockdb_fd; struct dkimf_dstring * sockdb_buf; }; #endif /* _FFR_SOCKETDB */ #ifdef USE_MDB struct dkimf_db_mdb { MDB_env * mdb_env; MDB_txn * mdb_txn; MDB_dbi mdb_dbi; }; #endif /* USE_MDB */ #ifdef USE_ERLANG struct dkimf_db_erlang { char * erlang_nodes; char * erlang_module; char * erlang_function; char * erlang_cookie; }; #endif /* USE_ERLANG */ /* globals */ struct dkimf_db_table dbtypes[] = { { "csl", DKIMF_DB_TYPE_CSL }, { "file", DKIMF_DB_TYPE_FILE }, { "refile", DKIMF_DB_TYPE_REFILE }, #ifdef USE_DB { "db", DKIMF_DB_TYPE_BDB }, #endif /* USE_DB */ #ifdef USE_ODBX { "dsn", DKIMF_DB_TYPE_DSN }, #endif /* USE_ODBX */ #ifdef USE_LDAP { "ldap", DKIMF_DB_TYPE_LDAP }, { "ldapi", DKIMF_DB_TYPE_LDAP }, { "ldaps", DKIMF_DB_TYPE_LDAP }, #endif /* USE_LDAP */ #ifdef USE_LUA { "lua", DKIMF_DB_TYPE_LUA }, #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED { "memcache", DKIMF_DB_TYPE_MEMCACHE }, #endif /* USE_LIBMEMCACHED */ #ifdef _FFR_REPUTATION { "repute", DKIMF_DB_TYPE_REPUTE }, #endif /* _FFR_REPUTATION */ #ifdef _FFR_SOCKETDB { "socket", DKIMF_DB_TYPE_SOCKET }, #endif /* _FFR_SOCKETDB */ #ifdef USE_MDB { "mdb", DKIMF_DB_TYPE_MDB }, #endif /* USE_MDB */ #ifdef USE_ERLANG { "erlang", DKIMF_DB_TYPE_ERLANG }, #endif /* USE_ERLANG */ { NULL, DKIMF_DB_TYPE_UNKNOWN }, }; static char *dkimf_db_ldap_param[DKIMF_LDAP_PARAM_MAX + 1]; #ifdef _FFR_DB_HANDLE_POOLS struct handle_pool { u_int hp_dbtype; u_int hp_max; u_int hp_alloc; u_int hp_asize; u_int hp_count; void * hp_hdata; void ** hp_handles; pthread_mutex_t hp_lock; pthread_cond_t hp_signal; }; #endif /* _FFR_DB_HANDLE_POOLS */ /* globals */ static unsigned int gflags = 0; #ifdef _FFR_DB_HANDLE_POOLS /* ** DKIMF_DB_HP_NEW -- create a handle pool ** ** Parameters: ** type -- DB type ** max -- maximum pool size ** hdata -- data needed to make new handles ** ** Return value: ** Pointer to a newly-allocated handle pool, or NULL on error. */ static struct handle_pool * dkimf_db_hp_new(u_int type, u_int max, void *hdata) { struct handle_pool *new; new = (struct handle_pool *) malloc(sizeof *new); if (new != NULL) { new->hp_alloc = 0; new->hp_asize = 0; new->hp_count = 0; new->hp_dbtype = type; new->hp_handles = NULL; new->hp_hdata = hdata; new->hp_max = max; pthread_mutex_init(&new->hp_lock, NULL); pthread_cond_init(&new->hp_signal, NULL); } return new; } /* ** DKIMF_DB_HP_FREE -- free a handle pool ** ** Parameters: ** pool -- bool to free up ** ** Return value: ** None. */ static void dkimf_db_hp_free(struct handle_pool *pool) { u_int c; assert(pool != NULL); for (c = 0; c < pool->hp_count; c++) { switch (pool->hp_dbtype) { #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: { odbx_t *odbx; odbx = (odbx_t *) pool->hp_handles[c]; (void) odbx_unbind(odbx); (void) odbx_finish(odbx); free(odbx); break; } #endif /* USE_ODBX */ default: break; } } pthread_mutex_destroy(&pool->hp_lock); pthread_cond_destroy(&pool->hp_signal); free(pool->hp_handles); free(pool); } /* ** DKIMF_DB_HP_GET -- get a handle from a handle pool ** ** Parameters: ** pool -- pool from which to get a handle ** err -- error code (returned) ** ** Return value: ** A handle appropriate to the associated DB type that is not currently ** in use by another thread, or NULL on error. */ static void * dkimf_db_hp_get(struct handle_pool *pool, int *err) { void *ret; assert(pool != NULL); pthread_mutex_lock(&pool->hp_lock); for (;;) { /* if one is available, return it */ if (pool->hp_count > 0) { ret = pool->hp_handles[0]; if (pool->hp_count > 1) { memmove(&pool->hp_handles[0], &pool->hp_handles[1], sizeof(void *) * (pool->hp_count - 1)); } pool->hp_count--; pthread_mutex_unlock(&pool->hp_lock); return ret; } /* if we can allocate one, do so */ if (pool->hp_alloc <= pool->hp_max) { switch (pool->hp_dbtype) { #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: { int dberr; odbx_t *odbx; struct dkimf_db_dsn *dsn; dsn = (struct dkimf_db_dsn *) pool->hp_hdata; dberr = odbx_init(&odbx, STRORNULL(dsn->dsn_backend), STRORNULL(dsn->dsn_host), STRORNULL(dsn->dsn_port)); if (dberr < 0) { if (err != NULL) *err = dberr; (void) odbx_finish(odbx); pthread_mutex_unlock(&pool->hp_lock); return NULL; } dberr = odbx_bind(odbx, STRORNULL(dsn->dsn_dbase), STRORNULL(dsn->dsn_user), STRORNULL(dsn->dsn_password), ODBX_BIND_SIMPLE); if (dberr < 0) { if (err != NULL) *err = dberr; (void) odbx_finish(odbx); pthread_mutex_unlock(&pool->hp_lock); return NULL; } ret = odbx; break; } #endif /* USE_ODBX */ default: assert(0); break; } pool->hp_alloc++; pthread_mutex_unlock(&pool->hp_lock); return ret; } /* already full; wait for one */ pthread_cond_wait(&pool->hp_signal, &pool->hp_lock); } } /* ** DKIMF_DB_HP_DEAD -- report that a handle found in the pool was dead ** ** Parameters: ** pool -- handle pool to be updated ** ** Return value: ** None. ** ** Notes: ** The caller is expected to identify a dead handle and deallocate it. */ static void dkimf_db_hp_dead(struct handle_pool *pool) { assert(pool != NULL); pthread_mutex_lock(&pool->hp_lock); pool->hp_alloc--; pthread_cond_signal(&pool->hp_signal); pthread_mutex_unlock(&pool->hp_lock); } /* ** DKIMF_DB_HP_PUT -- put a handle back into a handle pool after use ** ** Parameters: ** pool -- pool from which to get a handle ** handle -- handle being returned ** ** Return value: ** None. */ static void dkimf_db_hp_put(struct handle_pool *pool, void *handle) { assert(pool != NULL); assert(handle != NULL); pthread_mutex_lock(&pool->hp_lock); /* need to grow the array? */ if (pool->hp_asize == pool->hp_count) { u_int newasz; if (pool->hp_asize == 0) { newasz = DKIMF_DB_DEFASIZE; pool->hp_handles = (void **) malloc(newasz * sizeof(void *)); assert(pool->hp_handles != NULL); } else { void **newa; newasz = pool->hp_asize * 2; newa = (void **) realloc(pool->hp_handles, newasz * sizeof(void *)); assert(newa != NULL); pool->hp_handles = newa; } pool->hp_asize = newasz; } /* append it */ pool->hp_handles[pool->hp_count] = handle; /* increment the count */ pool->hp_count++; /* signal any waiters */ pthread_cond_signal(&pool->hp_signal); /* all done */ pthread_mutex_unlock(&pool->hp_lock); } #endif /* _FFR_DB_HANDLE_POOLS */ /* ** DKIMF_DB_FLAGS -- set global flags ** ** Parameters: ** flags -- new global flag mask ** ** Return value: ** None. */ void dkimf_db_flags(unsigned int flags) { gflags = flags; } #if (USE_SASL && USE_LDAP) /* ** DKIMF_DB_SASLINTERACT -- SASL binding interaction callback ** ** Parameters: ** ld -- LDAP handle (see below) ** flags -- LDAP handling flags ** defaults -- defaults pointer (see below) ** interact -- SASL interaction object ** ** Return value: ** LDAP_SUCCESS (for now) ** ** Notes: ** If SASL requires additional parameters that OpenLDAP didn't provide ** in its call, it uses a callback we have to provide to try to get them. ** The layering here can get quite confusing. "defaults" is an ** application-specific handle that can point to a bunch of defaults ** set elsewhere, but we don't need it here so it's ignored. Similarly, ** "ld" is not actually needed. */ static int dkimf_db_saslinteract(LDAP *ld, unsigned int flags, void *defaults, void *sasl_interact) { sasl_interact_t *interact; assert(sasl_interact != NULL); interact = sasl_interact; switch (interact->id) { case SASL_CB_PASS: interact->result = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_BINDPW]; interact->len = strlen(interact->result); break; case SASL_CB_GETREALM: interact->result = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_AUTHREALM]; interact->len = strlen(interact->result); break; case SASL_CB_AUTHNAME: interact->result = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_AUTHNAME]; interact->len = strlen(interact->result); break; case SASL_CB_USER: interact->result = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_AUTHUSER]; if (interact->result == NULL) interact->len = 0; else interact->len = strlen(interact->result); break; default: interact->result = ""; interact->len = 0; break; } return SASL_OK; } #endif /* (USE_SASL && USE_LDAP) */ #ifdef USE_ODBX /* ** DKIMF_DB_HEXDIGIT -- convert a hex digit to decimal value ** ** Parameters: ** c -- input character ** ** Return value: ** Converted value, or 0 on error. */ static int dkimf_db_hexdigit(int c) { if (c >= '0' && c <= '9') return c - '0'; else if (c >= 'A' && c <= 'F') return c - 'A' + 10; else if (c >= 'a' && c <= 'f') return c - 'f' + 10; else return 0; } #endif /* USE_ODBX */ /* ** DKIMF_DB_DATASPLIT -- split a database value or set of values into a ** request array ** ** Parameters: ** buf -- data buffer ** buflen -- buffer length ** req -- request array ** reqnum -- length of request array ** ** Return value: ** 0 -- successful data split ** -1 -- not enough elements present to fulfill the request */ static int dkimf_db_datasplit(char *buf, size_t buflen, DKIMF_DBDATA req, unsigned int reqnum) { int ridx; int ret = 0; size_t clen; size_t remain; char *p; assert(buf != NULL); if (req == NULL || reqnum == 0) return 0; p = buf; remain = buflen; for (ridx = 0; ridx < reqnum; ridx++) { if (remain <= 0) break; if ((req[ridx].dbdata_flags & DKIMF_DB_DATA_BINARY) != 0) { clen = MIN(remain, req[ridx].dbdata_buflen); memcpy(req[ridx].dbdata_buffer, p, clen); req[ridx].dbdata_buflen = remain; remain = 0; } else if (ridx == reqnum - 1) { clen = MIN(remain, req[ridx].dbdata_buflen); memcpy(req[ridx].dbdata_buffer, p, clen); req[ridx].dbdata_buflen = remain; } else { char *q; q = strchr(p, ':'); if (q != NULL) { clen = q - p; memcpy(req[ridx].dbdata_buffer, p, MIN(clen, req[ridx].dbdata_buflen)); req[ridx].dbdata_buflen = clen; p += clen + 1; remain -= (clen + 1); } else { clen = remain; memcpy(req[ridx].dbdata_buffer, p, MIN(clen, req[ridx].dbdata_buflen)); req[ridx].dbdata_buflen = clen; remain = 0; } } } /* mark the ones that got no data */ if (ridx < reqnum) { int c; for (c = ridx; c < reqnum; c++) { if ((req[c].dbdata_flags & DKIMF_DB_DATA_OPTIONAL) == 0) ret = -1; req[c].dbdata_buflen = (size_t) -1; } } return ret; } #ifdef USE_LDAP # define ISRFC2254CHR(q) ((q) == 0x2a || \ (q) == 0x28 || \ (q) == 0x29 || \ (q) == 0x5c || \ (q) == 0x00) # define ADDRFC2254CHR(x, y, z) { \ *(x)++ = '\\'; \ if ((y) > (x)) \ { \ (x) += snprintf((x), \ (y) - (x), \ "%02x", \ (z)); \ } \ } /* ** DKIMF_DB_MKLDAPQUERY -- generate an LDAP query ** ** Parameters: ** buf -- parameter (the actual query) ** query -- query string (a domain name?) ** out -- outbut buffer ** outlen -- size of "out" ** ** Return value: ** None. ** ** Notes: ** Expands "$d" and "$D" as defined in opendkim.conf(5). ** ** Should report overflows. */ static void dkimf_db_mkldapquery(char *buf, char *query, _Bool raw, char *out, size_t outlen) { char last = '\0'; char *p; char *o; char *q; char *pend; char *oend; char *qend; assert(buf != NULL); assert(query != NULL); assert(out != NULL); p = buf; pend = p + strlen(p) - 1; q = query; qend = query + strlen(query) - 1; o = out; oend = out + outlen - 1; while (p <= pend && o <= oend) { if (last == '$') { if (*p == 'd') { for (q = query; o <= oend && q <= qend; q++) { if (ISRFC2254CHR(*q) && !raw) { ADDRFC2254CHR(o, oend, *q); } else { *o++ = *q; } } } else if (*p == 'D') { for (q = query; o <= oend && q <= qend; q++) { if (q == query) { o += strlcpy(o, "dc=", oend - o); } if (*q == '.') { o += strlcpy(o, ",dc=", oend - o); } else if (ISRFC2254CHR(*q)) { ADDRFC2254CHR(o, oend, *q); } else { *o++ = *q; } } } else { *q++ = *p; } } else if (*p != '$') { *o++ = *p; } last = *p; p++; } } #endif /* USE_LDAP */ #ifdef USE_ODBX /* ** DKIMF_DB_NEXTPUNCT -- find next punctuation ** ** Parameters: ** str -- start of the search ** ** Return value: ** Pointer to the next punctuation found, or NULL if none. */ static char * dkimf_db_nextpunct(char *str) { char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (*p == ':' || *p == '/' || *p == '@' || *p == '+' || *p == '?') return p; if (*p == '=' && (!isxdigit(*(p + 1)) || !isxdigit(*(p + 2)))) return p; } return NULL; } #endif /* USE_ODBX */ /* ** DKIMF_DB_LIST_FREE -- destroy a linked list ** ** Parameters: ** list -- list handle ** ** Return value: ** None. */ static void dkimf_db_list_free(struct dkimf_db_list *list) { struct dkimf_db_list *next; assert(list != NULL); while (list != NULL) { free(list->db_list_key); if (list->db_list_value != NULL) free(list->db_list_value); next = list->db_list_next; free(list); list = next; } } /* ** DKIMF_DB_RELIST_FREE -- destroy a linked regex list ** ** Parameters: ** list -- list handle ** ** Return value: ** None. */ static void dkimf_db_relist_free(struct dkimf_db_relist *list) { struct dkimf_db_relist *next; assert(list != NULL); while (list != NULL) { regfree(&list->db_relist_re); if (list->db_relist_data != NULL) free(list->db_relist_data); next = list->db_relist_next; free(list); list = next; } } #ifdef USE_LDAP /* ** DKIMF_DB_OPEN_LDAP -- attempt to contact an LDAP server ** ** Parameters: ** ld -- LDAP handle (updated on success) ** ldap -- local LDAP data ** ** Return value: ** An LDAP_* constant. */ int dkimf_db_open_ldap(LDAP **ld, struct dkimf_db_ldap *ldap, char **err) { int v = LDAP_VERSION3; int n; int lderr; char *q; char *r; char *u; struct timeval timeout; assert(ld != NULL); assert(ldap != NULL); /* create LDAP handle */ lderr = ldap_initialize(ld, ldap->ldap_urilist); if (lderr != LDAP_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); return lderr; } /* set LDAP version */ lderr = ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &v); if (lderr != LDAP_OPT_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } /* enable auto-restarts */ lderr = ldap_set_option(*ld, LDAP_OPT_RESTART, LDAP_OPT_ON); if (lderr != LDAP_OPT_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } /* request timeouts */ q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_TIMEOUT]; timeout.tv_sec = DKIMF_LDAP_DEFTIMEOUT; timeout.tv_usec = 0; if (q != NULL) { errno = 0; timeout.tv_sec = strtoul(q, &r, 10); if (errno == ERANGE) timeout.tv_sec = DKIMF_LDAP_DEFTIMEOUT; } lderr = ldap_set_option(*ld, LDAP_OPT_TIMEOUT, &timeout); if (lderr != LDAP_OPT_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } /* request keepalive */ q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_KA_IDLE]; if (q != NULL) { errno = 0; n = strtoul(q, &r, 10); if (errno != ERANGE) { lderr = ldap_set_option(*ld, LDAP_OPT_X_KEEPALIVE_IDLE, &n); if (lderr != LDAP_OPT_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } } } q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_KA_PROBES]; if (q != NULL) { errno = 0; n = strtoul(q, &r, 10); if (errno != ERANGE) { lderr = ldap_set_option(*ld, LDAP_OPT_X_KEEPALIVE_PROBES, &n); if (lderr != LDAP_OPT_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } } } q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_KA_INTERVAL]; if (q != NULL) { errno = 0; n = strtoul(q, &r, 10); if (errno != ERANGE) { lderr = ldap_set_option(*ld, LDAP_OPT_X_KEEPALIVE_INTERVAL, &n); if (lderr != LDAP_OPT_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } } } /* attempt TLS if requested, except for ldaps */ q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_USETLS]; if (q != NULL && (*q == 'y' || *q == 'Y') && strcasecmp(ldap->ldap_descr->lud_scheme, "ldaps") != 0) { lderr = ldap_start_tls_s(*ld, NULL, NULL); if (lderr != LDAP_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } } /* attempt binding */ q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_AUTHMECH]; u = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_BINDUSER]; if (q == NULL || strcasecmp(q, "none") == 0 || strcasecmp(q, "simple") == 0) { struct berval passwd; r = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_BINDPW]; if (r != NULL) { passwd.bv_val = r; passwd.bv_len = strlen(r); } else { passwd.bv_val = NULL; passwd.bv_len = 0; } lderr = ldap_sasl_bind_s(*ld, u, q, &passwd, NULL, NULL, NULL); if (lderr != LDAP_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } } else { # ifdef USE_SASL lderr = ldap_sasl_interactive_bind_s(*ld, u, /* bind user */ q, /* SASL mech */ NULL, /* controls */ NULL, /* controls */ LDAP_SASL_QUIET, /* flags */ dkimf_db_saslinteract, /* callback */ NULL); if (lderr != LDAP_SUCCESS) { if (err != NULL) *err = ldap_err2string(lderr); ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return lderr; } # else /* USE_SASL */ /* unknown auth mechanism */ if (err != NULL) *err = "Unknown auth mechanism"; ldap_unbind_ext(*ld, NULL, NULL); *ld = NULL; return LDAP_AUTH_METHOD_NOT_SUPPORTED; # endif /* USE_SASL */ } return LDAP_SUCCESS; } #endif /* USE_LDAP */ #ifdef USE_ODBX /* ** DKIMF_DB_OPEN_SQL -- attempt to contact an SQL server ** ** Parameters: ** dsn -- connection description ** odbx -- ODBX handle (updated on success) ** err -- pointer to error string (updated on failure) ** ** Return value: ** Status from odbx_init(). */ int dkimf_db_open_sql(struct dkimf_db_dsn *dsn, odbx_t **odbx, char **err) { int dberr; assert(dsn != NULL); assert(odbx != NULL); /* create odbx handle */ dberr = odbx_init(odbx, STRORNULL(dsn->dsn_backend), STRORNULL(dsn->dsn_host), STRORNULL(dsn->dsn_port)); if (dberr < 0) { if (err != NULL) *err = (char *) odbx_error(NULL, dberr); return dberr; } /* create bindings */ dberr = odbx_bind(*odbx, STRORNULL(dsn->dsn_dbase), STRORNULL(dsn->dsn_user), STRORNULL(dsn->dsn_password), ODBX_BIND_SIMPLE); if (dberr < 0) { if (err != NULL) *err = (char *) odbx_error(*odbx, dberr); (void) odbx_finish(*odbx); return dberr; } return 0; } #endif /* USE_ODBX */ /* ** DKIMF_DB_TYPE -- return database type ** ** Parameters: ** db -- DKIMF_DB handle ** ** Return value: ** A DKIMF_DB_TYPE_* constant. */ int dkimf_db_type(DKIMF_DB db) { assert(db != NULL); return db->db_type; } #ifdef USE_ERLANG /* ** DKIMF_DB_ERL_CONNECT -- connect to a distributed Erlang node ** ** Parameters: ** db -- DKIMF_DB handle ** ecp -- Pointer to ei_cnode ** ** Return value: ** File descriptor or -1 on error. */ static int dkimf_db_erl_connect(DKIMF_DB db, ei_cnode *ecp) { int fd; int ret; int instance; unsigned int seed; char node_name[12]; struct timeval tv; char *q; char *last; struct dkimf_db_erlang *e; gettimeofday(&tv, NULL); seed = tv.tv_sec * tv.tv_usec; instance = rand_r(&seed) % 999; e = (struct dkimf_db_erlang *) db->db_data; snprintf(node_name, sizeof node_name, "opendkim%d", instance); ret = ei_connect_init(ecp, node_name, e->erlang_cookie, instance); if (ret != 0) return -1; fd = -1; for (q = strtok_r(e->erlang_nodes, ",", &last); q != NULL; q = strtok_r(NULL, ",", &last)) { fd = ei_connect(ecp, q); if (fd >= 0) break; } if (fd < 0) return -1; return fd; } /* ** DKIMF_DB_ERL_FREE -- free allocated memory for Erlang configuration ** ** Parameters: ** ep -- Pointer to struct dkimf_db_erlang ** ** Return value: ** None. */ static void dkimf_db_erl_free(struct dkimf_db_erlang *ep) { if (ep == NULL) return; if (ep->erlang_nodes != NULL) free(ep->erlang_nodes); if (ep->erlang_module != NULL) free(ep->erlang_module); if (ep->erlang_function != NULL) free(ep->erlang_function); if (ep->erlang_cookie != NULL) free(ep->erlang_cookie); free(ep); } /* ** DKIMF_DB_ERL_ALLOC_BUFFER -- allocate memory for a char* buffer ** depending on erlang response size ** ** Parameters: ** eip -- pointer to response ei_x_buff ** index -- pointer to current response index ** sizep -- size of response (returned) ** ** Return value: ** Pointer to allocated buffer or NULL on error. */ static char * dkimf_db_erl_alloc_buffer(ei_x_buff *eip, int *index, int *sizep) { int err; int type, size; err = ei_get_type(eip->buff, index, &type, &size); if (err < 0) return NULL; *sizep = size + 1; return malloc(*sizep); } /* ** DKIMF_DB_ERL_DECODE_ATOM -- decode an Erlang atom and check it ** against its desired value ** ** Parameters: ** eip -- pointer to response ei_x_buff ** index -- pointer to current response index ** cmp -- desired atom value ** ** Return value: ** 0 if the atom value matches de desired value, != 0 otherwise. */ static int dkimf_db_erl_decode_atom(ei_x_buff *eip, int *index, const char *cmp) { int err; int size; int ret; char *buf; buf = dkimf_db_erl_alloc_buffer(eip, index, &size); err = ei_decode_atom(eip->buff, index, buf); if (err != 0) return err; buf[size - 1] = '\0'; ret = strcmp(buf, cmp); free(buf); return ret; } /* ** DKIMF_DB_ERL_DECODE_TUPLE -- decode an Erlang tuple, optionally ** checking its arity ** ** Parameters: ** eip -- pointer to response ei_x_buff ** index -- pointer to current response index ** num_elements -- pointer desired tuple arity (returned) ** ** Return value: ** 0 -- success ** -1 -- error. ** ** Notes: ** If num_elements points to a positive number, the decoded tuple ** arity is checked against it, and if the values differ, the function ** will return an error. Otherwise, num_elements is set to the decoded ** tuple arity. */ static int dkimf_db_erl_decode_tuple(ei_x_buff *eip, int *index, int *num_elements) { int err; int arity; err = ei_decode_tuple_header(eip->buff, index, &arity); if (err < 0) return err; if (*num_elements > 0 && *num_elements != arity) return -1; *num_elements = arity; return 0; } /* ** DKIMF_DB_ERL_DECODE_BITSTRING -- decode an Erlang bitstring ** ** Parameters: ** eip -- pointer to response ei_x_buff ** index -- pointer to current response index ** ** Return value: ** Pointer to allocated buffer used to store the bitstring value ** or NULL on error. ** ** Notes: ** The caller is responsible for freeing the buffer. */ static char * dkimf_db_erl_decode_bitstring(ei_x_buff *eip, int *index) { int err; int size; long len; char *buf; buf = dkimf_db_erl_alloc_buffer(eip, index, &size); err = ei_decode_binary(eip->buff, index, buf, &len); if (err < 0) return NULL; buf[size - 1] = '\0'; return buf; } /* ** DKIMF_DB_ERL_DECODE_INTEGER -- decode an Erlang integer ** ** Parameters: ** eip -- pointer to response ei_x_buff ** index -- pointer to current response index ** val -- pointer to decoded integer (returned) ** ** Return value: ** 0: success ** < 0: error */ static int dkimf_db_erl_decode_int(ei_x_buff *eip, int *index, long *val) { int err; err = ei_decode_long(eip->buff, index, val); if (err < 0) return err; return 0; } /* ** DKIMF_DB_ERL_DECODE_RESPONSE -- decode an Erlang RPC response ** ** Parameters: ** resp -- pointer to response ei_x_buff ** notfound -- string containing the atom to be returned in case ** of a record not found ** req -- list of data requests ** reqnum -- number of data requests ** key -- buffer to receive the key (may be NULL) ** keylen -- bytes available at "key" (updated) ** ** Return value: ** -1: error ** 1: record not found ** 0: success ** ** Notes: ** Assumes keys returned from Erlang are either integers or ** bitstrings. */ static int dkimf_db_erl_decode_response(ei_x_buff *resp, const char *notfound, DKIMF_DBDATA req, unsigned int reqnum, char *key, size_t *keylen) { int ret; int res_index, res_type, res_size; res_index = 0; ret = ei_get_type(resp->buff, &res_index, &res_type, &res_size); if (ret != 0) return -1; switch (res_type) { case ERL_ATOM_EXT: { /* ** If we got an atom then it must signal record not found or ** no more records in the table. */ ret = dkimf_db_erl_decode_atom(resp, &res_index, notfound); if (ret != 0) return -1; return 1; } case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: { /* got a tuple {ok, something} */ int nres; int arity; arity = 2; ret = dkimf_db_erl_decode_tuple(resp, &res_index, &arity); if (ret == -1) return -1; ret = dkimf_db_erl_decode_atom(resp, &res_index, "ok"); if (ret != 0) return -1; ret = ei_get_type(resp->buff, &res_index, &res_type, &res_size); if (ret < 0) return -1; switch (res_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: { /* ** The tuple is {ok, IntegerDomainId} ** (we were called from SigningTable) */ int c; int n; long val; if (reqnum == 0) return 0; ret = dkimf_db_erl_decode_int(resp, &res_index, &val); if (ret != 0) return -1; n = snprintf(req[0].dbdata_buffer, req[0].dbdata_buflen, "%ld", val); req[0].dbdata_buflen = n + 1; for (c = 1; c < reqnum; c++) req[c].dbdata_buflen = 0; return 0; } case ERL_BINARY_EXT: { /* ** The tuple is {ok, BitstringDomainId} ** (we were called from SigningTable) */ int c; char *val; if (reqnum == 0) return 0; val = dkimf_db_erl_decode_bitstring(resp, &res_index); if (val == NULL) return -1; req[0].dbdata_buflen = strlcpy(req[0].dbdata_buffer, val, req[0].dbdata_buflen); free(val); for (c = 1; c < reqnum; c++) req[c].dbdata_buflen = 0; return 0; } case ERL_SMALL_TUPLE_EXT: case ERL_LARGE_TUPLE_EXT: { /* ** The tuple is either ** {ok, {Cursor, Domain, Selector, PrivKey}} ** (we were called from dkimf_db_walk()); or ** {ok, {Domain, Selector, PrivKey} ** (we were called from dkimf_db_get()). */ int c; arity = 0; ret = dkimf_db_erl_decode_tuple(resp, &res_index, &arity); if (ret == -1) return -1; if (key != NULL && keylen != NULL) { ret = ei_get_type(resp->buff, &res_index, &res_type, &res_size); if (ret != 0) return -1; switch (res_type) { case ERL_SMALL_INTEGER_EXT: case ERL_INTEGER_EXT: { int n; long val; ret = dkimf_db_erl_decode_int(resp, &res_index, &val); if (ret != 0) return -1; n = snprintf(key, *keylen, "%ld", val); *keylen = n + 1; break; } case ERL_BINARY_EXT: { char *val; val = dkimf_db_erl_decode_bitstring(resp, &res_index); if (val == NULL) return -1; *keylen = strlcpy(key, val, *keylen); free(val); break; } default: return -1; } } if (reqnum == 0) return 0; ret = ei_get_type(resp->buff, &res_index, &res_type, &res_size); if (ret != 0) return -1; nres = (key != NULL && keylen != NULL) ? arity - 1 : arity; for (c = 0; c < reqnum; c++) { if (c >= nres) { req[c].dbdata_buflen = 0; } else { char *val; val = dkimf_db_erl_decode_bitstring(resp, &res_index); if (val == NULL) return -1; req[c].dbdata_buflen = strlcpy(req[c].dbdata_buffer, val, req[c].dbdata_buflen); free(val); } } return 0; } default: return -1; } } default: return -1; } } #endif /* USE_ERLANG */ /* ** DKIMF_DB_OPEN -- open a database ** ** Parameters: ** db -- DKIMF_DB handle (returned) ** name -- name of DB to open ** flags -- operational flags ** lock -- lock to use during operations ** err -- error string from underlying library (returned; may be NULL) ** ** Return value: ** 3 -- other open error ** 2 -- illegal request (e.g. writable flat file) ** 1 -- unknown database type ** 0 -- success ** -1 -- failure; check errno ** ** Notes: ** The type of the database is implied by a leading "type:" string ** as part of "name". The list of valid types is listed in the ** "dbtypes" table above. Without such a prefix, a name that starts ** with "/" implies "file", otherwise "csl" is used. ** ** Currently defined types: ** csl -- "name" contains a comma-separated list ** file -- a flat file; may be simply a list of names if only a ** memership test is needed, or it can be "key value" lines ** in which case dkimf_db_get() can be used to extract the ** value of a named key ** refile -- a flat file containing patterns (i.e. strings with the ** wildcard "*"); only membership tests are allowed ** db -- a Sleepycat hash or b-tree database file, which can be used ** for membership tests or key-value pairs ** dsn -- a data store name, meaning SQL or ODBC in the backend, ** with interface provided by OpenDBX ** ldap -- an LDAP server, interace provide by OpenLDAP ** lua -- a Lua script; the returned value is the result ** erlang -- an erlang function to be called in a distributed erlang node */ int dkimf_db_open(DKIMF_DB *db, char *name, u_int flags, pthread_mutex_t *lock, char **err) { DKIMF_DB new; char *comma; char *p; assert(db != NULL); assert(name != NULL); new = (DKIMF_DB) malloc(sizeof(struct dkimf_db)); if (new == NULL) { if (err != NULL) *err = strerror(errno); return -1; } memset(new, '\0', sizeof(struct dkimf_db)); new->db_flags = (flags | gflags); new->db_type = DKIMF_DB_TYPE_UNKNOWN; p = strchr(name, ':'); comma = strchr(name, ','); /* catch a CSL that contains colons not in the first entry */ if (comma != NULL && p != NULL && comma < p) p = NULL; if (p == NULL) { # ifdef USE_DB char *q; q = NULL; for (p = strstr(name, ".db"); p != NULL; p = strstr(p + 1, ".db")) q = p; if (q != NULL && *(q + 3) == '\0') new->db_type = DKIMF_DB_TYPE_BDB; else # endif /* USE_DB */ if (name[0] == '/') new->db_type = DKIMF_DB_TYPE_FILE; else new->db_type = DKIMF_DB_TYPE_CSL; p = name; } else { int c; size_t clen; char dbtype[BUFRSZ + 1]; memset(dbtype, '\0', sizeof dbtype); clen = MIN(sizeof(dbtype) - 1, p - name); strncpy(dbtype, name, clen); for (c = 0; ; c++) { if (dbtypes[c].name == NULL) break; if (strcasecmp(dbtypes[c].name, dbtype) == 0) new->db_type = dbtypes[c].code; } if (new->db_type == DKIMF_DB_TYPE_UNKNOWN) { free(new); if (err != NULL) *err = "Unknown database type"; return 1; } p++; } /* force DB accesses to be mutex-protected */ if (new->db_type == DKIMF_DB_TYPE_DSN || new->db_type == DKIMF_DB_TYPE_SOCKET) new->db_flags |= DKIMF_DB_FLAG_MAKELOCK; /* use provided lock, or create a new one if needed */ if (lock != NULL) { new->db_lock = lock; new->db_flags &= ~DKIMF_DB_FLAG_MAKELOCK; } else if ((new->db_flags & DKIMF_DB_FLAG_MAKELOCK) != 0) { new->db_lock = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); if (new->db_lock == NULL) { if (err != NULL) *err = strerror(errno); free(new); return -1; } pthread_mutex_init(new->db_lock, NULL); } switch (new->db_type) { case DKIMF_DB_TYPE_CSL: { int n = 0; char *tmp; char *eq; char *ctx; struct dkimf_db_list *list = NULL; struct dkimf_db_list *next = NULL; struct dkimf_db_list *newl; if ((new->db_flags & DKIMF_DB_FLAG_READONLY) == 0) { free(new); errno = EINVAL; if (err != NULL) *err = strerror(errno); return 2; } tmp = strdup(p); if (tmp == NULL) { if (err != NULL) *err = strerror(errno); free(new); return -1; } for (p = strtok_r(tmp, ",", &ctx); p != NULL; p = strtok_r(NULL, ",", &ctx)) { eq = strchr(p, '='); if (eq != NULL) *eq = '\0'; if (eq != NULL && (new->db_flags & DKIMF_DB_FLAG_VALLIST) != 0) { char *q; char *ctx2; for (q = strtok_r(eq + 1, "|", &ctx2); q != NULL; q = strtok_r(NULL, "|", &ctx2)) { newl = (struct dkimf_db_list *) malloc(sizeof(struct dkimf_db_list)); if (newl == NULL) { if (err != NULL) *err = strerror(errno); if (list != NULL) dkimf_db_list_free(list); free(tmp); free(new); return -1; } newl->db_list_key = strdup(p); if (newl->db_list_key == NULL) { if (err != NULL) *err = strerror(errno); free(newl); if (list != NULL) dkimf_db_list_free(list); free(new); free(tmp); return -1; } dkimf_trimspaces(newl->db_list_key); newl->db_list_value = strdup(q); if (newl->db_list_value == NULL) { if (err != NULL) *err = strerror(errno); free(newl->db_list_key); free(newl); if (list != NULL) dkimf_db_list_free(list); free(tmp); free(new); return -1; } dkimf_trimspaces(newl->db_list_value); newl->db_list_next = NULL; if (list == NULL) list = newl; else next->db_list_next = newl; next = newl; n++; } } else { newl = (struct dkimf_db_list *) malloc(sizeof(struct dkimf_db_list)); if (newl == NULL) { if (err != NULL) *err = strerror(errno); if (list != NULL) dkimf_db_list_free(list); free(tmp); free(new); return -1; } newl->db_list_key = strdup(p); if (newl->db_list_key == NULL) { if (err != NULL) *err = strerror(errno); free(newl); if (list != NULL) dkimf_db_list_free(list); free(tmp); free(new); return -1; } dkimf_trimspaces(newl->db_list_key); if (eq != NULL) { newl->db_list_value = strdup(eq + 1); if (newl->db_list_value == NULL) { if (err != NULL) *err = strerror(errno); free(newl->db_list_key); free(newl); free(tmp); if (list != NULL) dkimf_db_list_free(list); free(new); return -1; } dkimf_trimspaces(newl->db_list_value); } else { newl->db_list_value = NULL; } newl->db_list_next = NULL; if (list == NULL) list = newl; else next->db_list_next = newl; next = newl; n++; } } free(tmp); new->db_handle = list; new->db_nrecs = n; break; } case DKIMF_DB_TYPE_FILE: { _Bool gapfound; int n = 0; FILE *f; char *key; char *value; struct dkimf_db_list *list = NULL; struct dkimf_db_list *next = NULL; struct dkimf_db_list *newl; char line[BUFRSZ + 1]; if ((new->db_flags & DKIMF_DB_FLAG_READONLY) == 0) { if (err != NULL) *err = strerror(EINVAL); free(new); errno = EINVAL; return 2; } f = fopen(p, "r"); if (f == NULL) { if (err != NULL) *err = strerror(errno); free(new); return -1; } memset(line, '\0', sizeof line); while (fgets(line, BUFRSZ, f) != NULL) { for (p = line; *p != '\0'; p++) { if (*p == '\n' || *p == '#') { *p = '\0'; break; } } dkimf_trimspaces((u_char *) line); if (strlen(line) == 0) continue; newl = (struct dkimf_db_list *) malloc(sizeof(struct dkimf_db_list)); if (newl == NULL) { if (err != NULL) *err = strerror(errno); if (list != NULL) dkimf_db_list_free(list); fclose(f); free(new); return -1; } key = NULL; value = NULL; gapfound = FALSE; for (p = line; *p != '\0'; p++) { if (!isascii(*p) || !isspace(*p)) { if (key == NULL) key = p; else if (value == NULL && gapfound) value = p; } else if (key != NULL && value == NULL) { *p = '\0'; gapfound = TRUE; } } assert(key != NULL); if (value != NULL && (new->db_flags & DKIMF_DB_FLAG_VALLIST) != 0) { char *q; char *ctx; for (q = strtok_r(value, "|", &ctx); q != NULL; q = strtok_r(NULL, "|", &ctx)) { newl = (struct dkimf_db_list *) malloc(sizeof(struct dkimf_db_list)); if (newl == NULL) { if (err != NULL) *err = strerror(errno); if (list != NULL) dkimf_db_list_free(list); free(new); return -1; } newl->db_list_key = strdup(key); if (newl->db_list_key == NULL) { if (err != NULL) *err = strerror(errno); free(newl); if (list != NULL) dkimf_db_list_free(list); free(new); return -1; } dkimf_trimspaces(newl->db_list_key); newl->db_list_value = strdup(q); if (newl->db_list_value == NULL) { if (err != NULL) *err = strerror(errno); free(newl->db_list_key); free(newl); if (list != NULL) dkimf_db_list_free(list); return -1; } dkimf_trimspaces(newl->db_list_value); newl->db_list_next = NULL; if (list == NULL) list = newl; else next->db_list_next = newl; next = newl; n++; } } else { newl->db_list_key = strdup(key); if (newl->db_list_key == NULL) { if (err != NULL) *err = strerror(errno); free(newl); if (list != NULL) dkimf_db_list_free(list); fclose(f); free(new); return -1; } dkimf_trimspaces(newl->db_list_key); if (value != NULL) { newl->db_list_value = strdup(value); if (newl->db_list_value == NULL) { if (err != NULL) *err = strerror(errno); free(newl->db_list_key); free(newl); if (list != NULL) dkimf_db_list_free(list); fclose(f); free(new); return -1; } dkimf_trimspaces(newl->db_list_value); } else { newl->db_list_value = NULL; } newl->db_list_next = NULL; if (list == NULL) list = newl; else next->db_list_next = newl; next = newl; n++; } } fclose(f); new->db_handle = list; new->db_nrecs = n; break; } case DKIMF_DB_TYPE_REFILE: { int status; int reflags; FILE *f; char *end; char *data; struct dkimf_db_relist *head = NULL; struct dkimf_db_relist *tail = NULL; struct dkimf_db_relist *newl; char line[BUFRSZ + 1]; char patbuf[BUFRSZ + 1]; if ((new->db_flags & DKIMF_DB_FLAG_READONLY) == 0) { if (err != NULL) *err = strerror(EINVAL); free(new); errno = EINVAL; return 2; } f = fopen(p, "r"); if (f == NULL) { if (err != NULL) *err = strerror(errno); free(new); return -1; } reflags = REG_EXTENDED; if ((new->db_flags & DKIMF_DB_FLAG_ICASE) != 0) reflags |= REG_ICASE; memset(line, '\0', sizeof line); while (fgets(line, BUFRSZ, f) != NULL) { end = NULL; data = NULL; for (p = line; *p != '\0'; p++) { if (*p == '\n' || *p == '#') { *p = '\0'; break; } else if (end == NULL && isascii(*p) && isspace(*p)) { end = p; } } if (end != NULL) { *end = '\0'; for (data = end + 1; *data != '\0'; data++) { if (!isascii(*data) || !isspace(*data)) break; } } dkimf_trimspaces((u_char *) line); if (strlen(line) == 0) continue; newl = (struct dkimf_db_relist *) malloc(sizeof(struct dkimf_db_relist)); if (newl == NULL) { if (err != NULL) *err = strerror(errno); if (head != NULL) dkimf_db_relist_free(head); fclose(f); free(new); free(newl); return -1; } memset(patbuf, '\0', sizeof patbuf); if (!dkimf_mkregexp(line, patbuf, sizeof patbuf)) { if (err != NULL) *err = "Error constructing regular expression"; if (head != NULL) dkimf_db_relist_free(head); fclose(f); free(new); free(newl); return -1; } status = regcomp(&newl->db_relist_re, patbuf, reflags); if (status != 0) { if (err != NULL) *err = "Error compiling regular expression"; if (head != NULL) dkimf_db_relist_free(head); fclose(f); free(new); free(newl); return -1; } if (data != NULL) { newl->db_relist_data = strdup(data); if (newl->db_relist_data == NULL) { if (err != NULL) *err = strerror(errno); if (head != NULL) dkimf_db_relist_free(head); fclose(f); free(new); free(newl); return -1; } dkimf_trimspaces(newl->db_relist_data); } else { newl->db_relist_data = NULL; } newl->db_relist_next = NULL; if (head == NULL) head = newl; else tail->db_relist_next = newl; tail = newl; } fclose(f); new->db_handle = head; break; } #ifdef USE_DB case DKIMF_DB_TYPE_BDB: { # if DB_VERSION_CHECK(2,0,0) int dbflags = 0; # endif /* DB_VERSION_CHECK(2,0,0) */ int status = 0; DBTYPE bdbtype; DB *newdb; # if DB_VERSION_CHECK(2,0,0) if ((new->db_flags & DKIMF_DB_FLAG_READONLY) != 0) { dbflags |= DB_RDONLY; bdbtype = DB_UNKNOWN; } else { dbflags |= DB_CREATE; bdbtype = DB_HASH; } # else /* DB_VERSION_CHECK(2,0,0) */ bdbtype = DB_HASH; # endif /* DB_VERSION_CHECK(2,0,0) */ if (*p == '\0') { new->db_flags |= DKIMF_DB_FLAG_NOFDLOCK; flags = new->db_flags; p = NULL; } # if DB_VERSION_CHECK(3,0,0) status = db_create(&newdb, NULL, 0); if (status == 0) { # if DB_VERSION_CHECK(4,1,25) status = newdb->open(newdb, NULL, p, NULL, bdbtype, dbflags, 0); # else /* DB_VERSION_CHECK(4,1,25) */ status = newdb->open(newdb, p, NULL, bdbtype, dbflags, 0); # endif /* DB_VERSION_CHECK(4,1,25) */ } # elif DB_VERSION_CHECK(2,0,0) status = db_open(p, bdbtype, dbflags, DKIMF_DB_MODE, NULL, NULL, &newdb); # else /* DB_VERSION_CHECK(2,0,0) */ newdb = dbopen(p, (new->db_flags & DKIMF_DB_FLAG_READONLY ? O_RDONLY : (O_CREAT|O_RDWR)), DKIMF_DB_MODE, bdbtype, NULL); if (newdb == NULL) status = errno; # endif /* DB_VERSION_CHECK */ if (status != 0) { if (err != NULL) *err = DB_STRERROR(status); free(new); return 3; } new->db_handle = newdb; break; } #endif /* USE_DB */ #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: { _Bool found; int dberr; struct dkimf_db_dsn *dsn; char *q; char *r; char *eq; char *tmp; odbx_t *odbx; dsn = (struct dkimf_db_dsn *) malloc(sizeof(struct dkimf_db_dsn)); if (dsn == NULL) { if (err != NULL) *err = strerror(errno); free(new); return -1; } memset(dsn, '\0', sizeof *dsn); /* ** General format of a DSN: ** ://[user[:pwd]@][port+]host/dbase[/key=val[?...]] ** ** "table", "keycol" and "datacol" will be set in one of the ** key-value pairs. "filter" is optional. */ tmp = strdup(p); if (tmp == NULL) { if (err != NULL) *err = strerror(errno); free(dsn); free(new); return -1; } q = strchr(tmp, ':'); if (q == NULL) { if (err != NULL) *err = strerror(EINVAL); free(dsn); free(tmp); free(new); return -1; } *q = '\0'; strlcpy(dsn->dsn_backend, tmp, sizeof dsn->dsn_backend); q++; if (*q != '/' || *(q + 1) != '/') { if (err != NULL) *err = strerror(EINVAL); free(dsn); free(tmp); return -1; } q += 2; found = FALSE; for (p = dkimf_db_nextpunct(q); !found && p != NULL; p = dkimf_db_nextpunct(q)) { switch (*p) { case ':': *p = '\0'; if (dsn->dsn_user[0] != '\0') { if (err != NULL) *err = strerror(EINVAL); free(dsn); free(tmp); free(new); return -1; } strlcpy(dsn->dsn_user, q, sizeof dsn->dsn_user); q = p + 1; break; case '@': *p = '\0'; if (dsn->dsn_user[0] == '\0') { strlcpy(dsn->dsn_user, q, sizeof dsn->dsn_user); } else { strlcpy(dsn->dsn_password, q, sizeof dsn->dsn_password); } q = p + 1; break; case '+': *p = '\0'; strlcpy(dsn->dsn_port, q, sizeof dsn->dsn_port); q = p + 1; break; case '/': *p = '\0'; if (dsn->dsn_host[0] == '\0') { strlcpy(dsn->dsn_host, q, sizeof dsn->dsn_host); } else { found = TRUE; strlcpy(dsn->dsn_dbase, q, sizeof dsn->dsn_dbase); } q = p + 1; break; default: if (err != NULL) *err = strerror(EINVAL); free(dsn); free(tmp); free(new); return -1; } } if (dsn->dsn_host[0] == '\0') { if (err != NULL) *err = "SQL host not defined"; free(dsn); free(tmp); free(new); return -1; } for (p = strtok_r(q, "?", &r); p != NULL; p = strtok_r(NULL, "?", &r)) { eq = strchr(p, '='); if (eq == NULL) continue; *eq = '\0'; if (strcasecmp(p, "table") == 0) { strlcpy(dsn->dsn_table, eq + 1, sizeof dsn->dsn_table); } else if (strcasecmp(p, "keycol") == 0) { strlcpy(dsn->dsn_keycol, eq + 1, sizeof dsn->dsn_keycol); } else if (strcasecmp(p, "datacol") == 0) { strlcpy(dsn->dsn_datacol, eq + 1, sizeof dsn->dsn_datacol); } else if (strcasecmp(p, "filter") == 0) { size_t len; len = strlen(eq + 1) + 1; dsn->dsn_filter = malloc(len); if (dsn->dsn_filter != NULL) { int c; char *q; char *r; memset((void *) dsn->dsn_filter, '\0', len); r = (char *) dsn->dsn_filter; for (q = eq + 1; q < eq + len; q++) { if (*q == '=' && isxdigit(*(q + 1)) && isxdigit(*(q + 2))) { c = 16 * dkimf_db_hexdigit(*(q + 1)); c += dkimf_db_hexdigit(*(q + 2)); *r++ = c; q += 2; } else { *r++ = *q; } } } } } /* error out if one of the required parameters was absent */ if (dsn->dsn_table[0] == '\0' || dsn->dsn_keycol[0] == '\0' || dsn->dsn_datacol[0] == '\0') { if (err != NULL) *err = strerror(EINVAL); free(dsn); free(tmp); free(new); return -1; } # ifdef _FFR_DB_HANDLE_POOLS new->db_handle = dkimf_db_hp_new(new->db_type, DEFPOOLMAX, dsn); if (new == NULL) { if (err != NULL) *err = strerror(errno); free(dsn); free(tmp); free(new); return -1; } # else /* _FFR_DB_HANDLE_POOLS */ /* create odbx handle */ if (dkimf_db_open_sql(dsn, &odbx, err) < 0) { if ((new->db_flags & DKIMF_DB_FLAG_SOFTSTART) == 0) { free(dsn); free(tmp); free(new); return -1; } new->db_iflags |= DKIMF_DB_IFLAG_RECONNECT; odbx = NULL; } /* store handle */ new->db_handle = (void *) odbx; # endif /* _FFR_DB_HANDLE_POOLS */ new->db_data = (void *) dsn; /* clean up */ free(tmp); break; } #endif /* USE_ODBX */ #ifdef USE_LDAP case DKIMF_DB_TYPE_LDAP: { int c; int lderr; size_t rem; size_t plen; struct dkimf_db_ldap *ldap; LDAP *ld; char *q; char *r; LDAPURLDesc *descr; #ifdef _FFR_LDAP_CACHING # ifdef USE_DB DB *newdb; # endif /* USE_DB */ #endif /* _FFR_LDAP_CACHING */ char *uris[DKIMF_LDAP_MAXURIS]; memset(uris, '\0', sizeof uris); p = strdup(name); if (p == NULL) { if (err != NULL) *err = strerror(errno); free(new); return -1; } /* make sure they're all valid LDAP URIs */ for (q = strtok_r(p, " \t", &r), c = 0; q != NULL; q = strtok_r(NULL, " \t", &r), c++) { if (ldap_is_ldap_url(q) == 0) { if (err != NULL) *err = strerror(EINVAL); free(p); free(new); return -1; } /* store the first N of them */ if (c < DKIMF_LDAP_MAXURIS) uris[c] = q; } ldap = (struct dkimf_db_ldap *) malloc(sizeof(struct dkimf_db_ldap)); if (ldap == NULL) { if (err != NULL) *err = strerror(errno); free(p); free(new); return -1; } memset(ldap, '\0', sizeof *ldap); q = dkimf_db_ldap_param[DKIMF_LDAP_PARAM_TIMEOUT]; if (q == NULL) { ldap->ldap_timeout = DKIMF_LDAP_DEFTIMEOUT; } else { errno = 0; ldap->ldap_timeout = strtoul(q, &r, 10); if (errno == ERANGE) ldap->ldap_timeout = DKIMF_LDAP_DEFTIMEOUT; } /* ** General format of an LDAP specification: ** scheme://host[:port][/dn[?attrs[?scope[?filter[?exts]]]]] ** (see RFC4516) ** ** "bindpass", "authmech" and "usetls" will be set in ** other config values. ** ** Take the descriptive values (e.g. attributes) from the ** first one. */ lderr = ldap_url_parse(uris[0], &ldap->ldap_descr); if (lderr != 0) { if (err != NULL) *err = ldap_err2string(lderr); free(ldap); free(p); free(new); return -1; } /* construct the URI list for this handle */ rem = sizeof ldap->ldap_urilist; q = ldap->ldap_urilist; for (c = 0; c < DKIMF_LDAP_MAXURIS; c++) { if (uris[c] == NULL) break; (void) ldap_url_parse(uris[c], &descr); if (c != 0) { *q = ' '; q++; rem--; } plen = snprintf(q, rem, "%s://%s:%d", descr->lud_scheme, descr->lud_host, descr->lud_port); if (plen >= rem) { if (err != NULL) *err = "LDAP URI too large"; free(ldap); free(p); free(new); return -1; } q += plen; rem -= plen; ldap_free_urldesc(descr); } lderr = dkimf_db_open_ldap(&ld, ldap, err); if (lderr != LDAP_SUCCESS) { if ((new->db_flags & DKIMF_DB_FLAG_SOFTSTART) == 0) { if (err != NULL) *err = ldap_err2string(lderr); free(ldap); free(p); free(new); return -1; } else { ld = NULL; } } pthread_mutex_init(&ldap->ldap_lock, NULL); # ifdef _FFR_LDAP_CACHING # ifdef USE_DB if ((new->db_flags & DKIMF_DB_FLAG_NOCACHE) == 0) { /* establish LDAP cache DB */ lderr = 0; # if DB_VERSION_CHECK(3,0,0) lderr = db_create(&newdb, NULL, 0); if (lderr == 0) { # if DB_VERSION_CHECK(4,1,25) lderr = newdb->open(newdb, NULL, NULL, NULL, DB_HASH, DB_CREATE, 0); # else /* DB_VERSION_CHECK(4,1,25) */ lderr = newdb->open(newdb, NULL, NULL, DB_HASH, DB_CREATE, 0); # endif /* DB_VERSION_CHECK(4,1,25) */ } # elif DB_VERSION_CHECK(2,0,0) lderr = db_open(NULL, DB_HASH, 0, DKIMF_DB_MODE, NULL, NULL, &newdb); # else /* DB_VERSION_CHECK(2,0,0) */ newdb = dbopen(NULL, (O_CREAT|O_RDWR), DKIMF_DB_MODE, DB_HASH, NULL); if (newdb == NULL) lderr = errno; # endif /* DB_VERSION_CHECK */ if (lderr == 0) { DKIMF_DB cachedb; cachedb = malloc(sizeof *cachedb); if (cachedb != NULL) { memset(cachedb, '\0', sizeof *cachedb); cachedb->db_type = DKIMF_DB_TYPE_BDB; cachedb->db_handle = newdb; ldap->ldap_cache = cachedb; } else { DKIMF_DBCLOSE(newdb); } } } # endif /* USE_DB */ # endif /* _FFR_LDAP_CACHING */ /* store handle */ new->db_handle = (void *) ld; new->db_data = (void *) ldap; /* clean up */ free(p); break; } #endif /* USE_LDAP */ #ifdef USE_LUA case DKIMF_DB_TYPE_LUA: { int fd; ssize_t rlen; char *tmp; struct stat s; struct dkimf_lua_script_result lres; struct dkimf_db_lua *lua; fd = open(p, O_RDONLY); if (fd < 0) { if (err != NULL) *err = strerror(errno); return -1; } if (fstat(fd, &s) == -1) { if (err != NULL) *err = strerror(errno); close(fd); return -1; } lua = (struct dkimf_db_lua *) malloc(sizeof *lua); if (lua == NULL) { if (err != NULL) *err = strerror(errno); return -1; } memset(lua, '\0', sizeof *lua); new->db_data = (void *) lua; tmp = (void *) malloc(s.st_size + 1); if (tmp == NULL) { if (err != NULL) *err = strerror(errno); free(new->db_data); close(fd); return -1; } memset(tmp, '\0', s.st_size + 1); rlen = read(fd, tmp, s.st_size); if (rlen < s.st_size) { if (err != NULL) { if (rlen == -1) *err = strerror(errno); else *err = "Read truncated"; } free(tmp); free(new->db_data); close(fd); return -1; } close(fd); /* try to compile it */ if (dkimf_lua_db_hook(tmp, 0, NULL, &lres, (void *) &lua->lua_script, &lua->lua_scriptlen) != 0) { if (err != NULL) *err = "Lua compilation error"; free(tmp); free(new->db_data); return -1; } free(tmp); break; } #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED case DKIMF_DB_TYPE_MEMCACHE: { in_port_t port; char *colon; char *q; char *key; char *last; char *tmp; memcached_st *mcs = NULL; tmp = strdup(p); if (tmp == NULL) return -1; q = strchr(tmp, '/'); if (q == NULL) { free(tmp); return -1; } *q = '\0'; key = strdup(q + 1); if (key == NULL) { free(tmp); return -1; } mcs = memcached_create(NULL); if (mcs == NULL) { free(tmp); free(key); return -1; } for (q = strtok_r(tmp, ",", &last); q != NULL; q = strtok_r(NULL, ",", &last)) { colon = strchr(q, ':'); if (colon != NULL) *colon = '\0'; if (colon == NULL) port = MEMCACHED_DEFAULT_PORT; else port = atoi(colon + 1); if (memcached_server_add(mcs, q, port) != MEMCACHED_SUCCESS) { free(tmp); free(key); memcached_free(mcs); return -1; } } new->db_handle = mcs; new->db_data = key; free(tmp); break; } #endif /* USE_LIBMEMCACHED */ #ifdef _FFR_REPUTATION case DKIMF_DB_TYPE_REPUTE: { unsigned int reporter = 0; char *q; REPUTE r; char useragent[BUFRSZ + 1]; q = strchr(p, ':'); if (q != NULL) { char *s; *q = '\0'; reporter = (unsigned int) strtoul(q + 1, &s, 10); if (*s != '\0') return -1; } r = repute_new(p, reporter); if (r == NULL) return -1; q = (char *) repute_curlversion(r); snprintf(useragent, sizeof useragent, "%s/%s %s%s%s", DKIMF_PRODUCTNS, VERSION, "libcurl", q == NULL ? "" : "/", q == NULL ? "" : q); repute_useragent(r, useragent); new->db_data = (void *) r; break; } #endif /* _FFR_REPUTATION */ #ifdef _FFR_SOCKETDB case DKIMF_DB_TYPE_SOCKET: { int fd; int status; struct dkimf_db_socket *sdb; sdb = (struct dkimf_db_socket *) malloc(sizeof *sdb); if (sdb == NULL) { if (err != NULL) *err = strerror(errno); free(new); return 2; } if ((new->db_flags & DKIMF_DB_FLAG_READONLY) == 0) { if (err != NULL) *err = strerror(EINVAL); free(new); errno = EINVAL; return 2; } if (*p == '/') { /* UNIX domain */ struct sockaddr_un sun; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { if (err != NULL) *err = strerror(errno); free(new); return 2; } memset(&sun, '\0', sizeof sun); sun.sun_family = AF_UNIX; #ifdef HAVE_SUN_LEN sun.sun_len = sizeof(sun); #endif /* HAVE_SUN_LEN */ strlcpy(sun.sun_path, p, sizeof(sun.sun_path)); status = connect(fd, (struct sockaddr *) &sun, sizeof sun); if (status < 0) { if (err != NULL) *err = strerror(errno); free(new); return 2; } } else { /* port@host */ int af; char *at; char *q; uint16_t port; struct in_addr ip4; # ifdef AF_INET6 struct in6_addr ip6; # endif /* AF_INET6 */ at = strchr(p, '@'); if (at == NULL) { if (err != NULL) *err = strerror(EINVAL); free(new); errno = EINVAL; return 2; } *at = '\0'; port = (uint16_t) strtoul(p, &q, 10); if (*q != '\0') { struct servent *srv; srv = getservbyname(p, "tcp"); if (srv == NULL) { if (err != NULL) *err = strerror(EINVAL); free(new); errno = EINVAL; return 2; } port = srv->s_port; } else { port = htons(port); } fd = -1; if (inet_pton(AF_INET, at + 1, &ip4) == 1) { af = AF_INET; } # ifdef AF_INET6 else if (inet_pton(AF_INET6, at + 1, &ip6) == 1) { af = AF_INET6; } # endif /* AF_INET6 */ else { # ifdef HAVE_GETADDRINFO int save_errno; struct addrinfo hint; struct addrinfo *aitop; struct addrinfo *aicur; struct protoent *proto; proto = getprotobyname("tcp"); if (proto == NULL) { if (err != NULL) *err = strerror(EPROTONOSUPPORT); free(new); errno = EPROTONOSUPPORT; return 2; } memset(&hint, '\0', sizeof hint); hint.ai_protocol = proto->p_proto; status = getaddrinfo(at + 1, p, &hint, &aitop); if (status != 0) { if (err != NULL) *err = (char *) gai_strerror(status); free(new); errno = EINVAL; return 2; } for (aicur = aitop; aicur != NULL; aicur = aicur->ai_next) { fd = socket(aicur->ai_family, aicur->ai_socktype, aicur->ai_protocol); if (fd == -1) { save_errno = errno; continue; } status = connect(fd, aicur->ai_addr, aicur->ai_addrlen); if (status == 0) break; save_errno = errno; close(fd); fd = -1; } freeaddrinfo(aitop); if (fd == -1) { if (err != NULL) *err = strerror(save_errno); free(new); errno = save_errno; return 2; } # else /* HAVE_GETADDRINFO */ struct hostent *h; struct sockaddr_in sin4; # ifdef HAVE_GETHOSTBYNAME2 struct sockaddr_in6 sin6; h = gethostbyname2(at + 1, AF_INET6); if (h != NULL) { af = AF_INET6; fd = socket(AF_INET6, SOCK_STREAM, 0); if (fd < 0) { if (err != NULL) *err = strerror(errno); free(new); return 2; } for (c = 0; h->h_addr_list[c] != NULL; c++) { memset(&sin6, '\0', sizeof sin6); sin6.sin6_family = AF_INET6; sin6.sin6_port = port; memcpy(&sin6.sin6_addr, h->h_addr_list[c], sizeof sin6.sin6_addr); status = connect(fd, (struct sockaddr *) &sin6, sizeof sin6); if (status == 0) break; save_errno = errno; } close(fd); fd = -1; } # endif /* HAVE_GETHOSTBYNAME2 */ h = gethostbyname(at + 1); if (h != NULL) { af = AF_INET; fd = socket(AF_INET, SOCK_STREAM, 0); if (fd < 0) { if (err != NULL) *err = strerror(errno); free(new); return 2; } for (c = 0; h->h_addr_list[c] != NULL; c++) { memset(&sin4, '\0', sizeof sin4); sin.sin_family = AF_INET; sin.sin_port = port; memcpy(&sin.sin_addr, h->h_addr_list[c], sizeof sin.sin_addr); status = connect(fd, (struct sockaddr *) &sin4, sizeof sin4); if (status == 0) break; save_errno = errno; } close(fd); fd = -1; } if (fd == -1) { if (err != NULL) *err = strerror(save_errno); free(new); errno = save_errno; return 2; } # endif /* HAVE_GETADDRINFO */ } if (fd == -1) { int save_errno; fd = socket(af, SOCK_STREAM, 0); if (fd < 0) { if (err != NULL) *err = strerror(errno); free(new); return 2; } # ifdef AF_INET6 if (af == AF_INET6) { struct sockaddr_in6 sin6; memset(&sin6, '\0', sizeof sin6); sin6.sin6_family = AF_INET6; sin6.sin6_port = port; memcpy(&sin6.sin6_addr, &ip6, sizeof sin6.sin6_addr); status = connect(fd, (struct sockaddr *) &sin6, sizeof sin6); if (status != 0) { save_errno = errno; close(fd); if (err != NULL) *err = strerror(save_errno); free(new); return 2; } } # endif /* AF_INET6 */ if (af == AF_INET) { struct sockaddr_in sin4; memset(&sin4, '\0', sizeof sin4); sin4.sin_family = AF_INET; sin4.sin_port = port; memcpy(&sin4.sin_addr, &ip4, sizeof sin4.sin_addr); status = connect(fd, (struct sockaddr *) &sin4, sizeof sin4); if (status != 0) { save_errno = errno; close(fd); if (err != NULL) *err = strerror(save_errno); free(new); return 2; } } } } sdb->sockdb_fd = fd; sdb->sockdb_buf = dkimf_dstring_new(BUFRSZ, 0); new->db_handle = sdb; break; } #endif /* _FFR_SOCKETDB */ #ifdef USE_MDB case DKIMF_DB_TYPE_MDB: { int status; struct dkimf_db_mdb *mdb; mdb = (struct dkimf_db_mdb *) malloc(sizeof *mdb); if (mdb == NULL) return -1; status = mdb_env_create(&mdb->mdb_env); if (status != 0) { if (err != NULL) *err = mdb_strerror(status); free(mdb); return -1; } status = mdb_env_open(mdb->mdb_env, p, 0, 0); if (status != 0) { if (err != NULL) *err = mdb_strerror(status); mdb_env_close(mdb->mdb_env); free(mdb); return -1; } status = mdb_txn_begin(mdb->mdb_env, NULL, 0, &mdb->mdb_txn); if (status != 0) { if (err != NULL) *err = mdb_strerror(status); mdb_env_close(mdb->mdb_env); free(mdb); return -1; } status = mdb_dbi_open(mdb->mdb_txn, NULL, 0, &mdb->mdb_dbi); if (status != 0) { if (err != NULL) *err = mdb_strerror(status); mdb_txn_abort(mdb->mdb_txn); mdb_env_close(mdb->mdb_env); free(mdb); return -1; } new->db_data = (void *) mdb; break; } #endif /* USE_MDB */ #ifdef USE_ERLANG case DKIMF_DB_TYPE_ERLANG: { _Bool err = FALSE; int c; char *q; char *last; char *r; char *tmp; struct dkimf_db_erlang *e; /* ** Erlang dataset configuration format: ** erlang:node1,node2,...:cookie:module:function */ tmp = strdup(p); if (tmp == NULL) return -1; e = calloc(1, sizeof *e); if (e == NULL) { free(tmp); return -1; } c = 0; for (q = strtok_r(tmp, ":", &last); !err && q != NULL; q = strtok_r(NULL, ":", &last)) { switch (c) { case 0: e->erlang_nodes = strdup(q); if (e->erlang_nodes == NULL) err = TRUE; break; case 1: e->erlang_cookie = strdup(q); if (e->erlang_cookie == NULL) err = TRUE; break; case 2: e->erlang_module = strdup(q); if (e->erlang_module == NULL) err = TRUE; break; case 3: e->erlang_function = strdup(q); if (e->erlang_function == NULL) err = TRUE; break; case 4: err = TRUE; break; } c++; } if (err || c < 3) { free(tmp); dkimf_db_erl_free(e); return -1; } new->db_data = e; free(tmp); break; } #endif /* USE_ERLANG */ } *db = new; return 0; } /* ** DKIMF_DB_DELETE -- delete a key/data pair from an open database ** ** Parameters: ** db -- DB handle to use for searching ** buf -- pointer to record to be deleted ** buflen -- size of record at "buf"; if 0, use strlen() ** ** Return value: ** 0 -- operation successful ** !0 -- error occurred; error code returned */ int dkimf_db_delete(DKIMF_DB db, void *buf, size_t buflen) { int ret = EINVAL; #ifdef USE_DB DBT q; int fd; int status; DB *bdb; #endif /* USE_DB */ assert(db != NULL); assert(buf != NULL); if (db->db_type == DKIMF_DB_TYPE_FILE || db->db_type == DKIMF_DB_TYPE_CSL || db->db_type == DKIMF_DB_TYPE_DSN || db->db_type == DKIMF_DB_TYPE_LDAP || db->db_type == DKIMF_DB_TYPE_LUA || db->db_type == DKIMF_DB_TYPE_MEMCACHE || db->db_type == DKIMF_DB_TYPE_REPUTE || db->db_type == DKIMF_DB_TYPE_REFILE || db->db_type == DKIMF_DB_TYPE_ERLANG) return EINVAL; #ifdef USE_DB bdb = (DB *) db->db_handle; memset(&q, 0, sizeof q); q.data = (char *) buf; q.size = (buflen == 0 ? strlen(q.data) : buflen); ret = 0; /* establish write-lock */ fd = -1; status = 0; if ((db->db_flags & DKIMF_DB_FLAG_NOFDLOCK) == 0) { # if DB_VERSION_CHECK(2,0,0) status = bdb->fd(bdb, &fd); # else /* DB_VERSION_CHECK(2,0,0) */ fd = bdb->fd(bdb); # endif /* DB_VERSION_CHECK(2,0,0) */ } if (db->db_lock != NULL) (void) pthread_mutex_lock(db->db_lock); if (status == 0 && fd != -1) { # ifdef LOCK_EX status = flock(fd, LOCK_EX); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # else /* LOCK_EX */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_WRLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # endif /* LOCK_EX */ } # if DB_VERSION_CHECK(2,0,0) status = bdb->del(bdb, NULL, &q, 0); if (status == 0) ret = 0; else ret = status; # else /* DB_VERSION_CHECK(2,0,0) */ status = bdb->del(bdb, &q, 0); if (status == 1) ret = -1; else if (status == 0) ret = 0; else ret = errno; # endif /* DB_VERSION_CHECK(2,0,0) */ /* surrender write-lock */ if (fd != -1) { # ifdef LOCK_UN status = flock(fd, LOCK_UN); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # else /* LOCK_UN */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_UNLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # endif /* LOCK_UN */ } if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); #endif /* USE_DB */ return ret; } /* ** DKIMF_DB_PUT -- store a key/data pair in an open database ** ** Parameters: ** db -- DB handle to use for searching ** buf -- pointer to key record ** buflen -- size of key (use strlen() if 0) ** outbuf -- data buffer ** outbuflen -- number of bytes at outbuf to use as data ** ** Return value: ** 0 -- operation successful ** !0 -- error occurred; error code returned */ int dkimf_db_put(DKIMF_DB db, void *buf, size_t buflen, void *outbuf, size_t outbuflen) { int ret = EINVAL; #ifdef USE_DB DBT d; DBT q; int fd; int status; DB *bdb; #endif /* USE_DB */ #ifdef USE_MDB MDB_val key; MDB_val data; MDB_dbi dbi; MDB_txn *txn; struct dkimf_db_mdb *mdb; #endif /* USE_MDB */ assert(db != NULL); assert(buf != NULL); assert(outbuf != NULL); if (db->db_type == DKIMF_DB_TYPE_FILE || db->db_type == DKIMF_DB_TYPE_CSL || db->db_type == DKIMF_DB_TYPE_DSN || db->db_type == DKIMF_DB_TYPE_LDAP || db->db_type == DKIMF_DB_TYPE_LUA || db->db_type == DKIMF_DB_TYPE_REPUTE || db->db_type == DKIMF_DB_TYPE_REFILE) return EINVAL; #ifdef USE_DB bdb = (DB *) db->db_handle; memset(&d, 0, sizeof d); memset(&q, 0, sizeof q); d.data = outbuf; d.size = outbuflen; # if DB_VERSION_CHECK(2,0,0) d.ulen = d.size; d.flags = DB_DBT_USERMEM; # endif /* DB_VERSION_CHECK(2,0,0) */ q.data = (char *) buf; q.size = (buflen == 0 ? strlen(q.data) : buflen); # if DB_VERSION_CHECK(2,0,0) q.ulen = q.size; q.flags = DB_DBT_USERMEM; # endif /* DB_VERSION_CHECK(2,0,0) */ ret = 0; /* establish write-lock */ fd = -1; status = 0; if ((db->db_flags & DKIMF_DB_FLAG_NOFDLOCK) == 0) { # if DB_VERSION_CHECK(2,0,0) status = bdb->fd(bdb, &fd); if (status != 0) { db->db_status = status; return status; } # else /* DB_VERSION_CHECK(2,0,0) */ fd = bdb->fd(bdb); # endif /* DB_VERSION_CHECK(2,0,0) */ } if (db->db_lock != NULL) (void) pthread_mutex_lock(db->db_lock); if (status == 0 && fd != -1) { # ifdef LOCK_EX status = flock(fd, LOCK_EX); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # else /* LOCK_EX */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_WRLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # endif /* LOCK_EX */ } # if DB_VERSION_CHECK(2,0,0) status = bdb->put(bdb, NULL, &q, &d, 0); if (status == 0) { ret = 0; } else { db->db_status = status; ret = status; } # else /* DB_VERSION_CHECK(2,0,0) */ status = bdb->put(bdb, &q, &d, 0); if (status == 1) { ret = -1; } else if (status == 0) { ret = 0; } else { db->db_status = status; ret = errno; } # endif /* DB_VERSION_CHECK(2,0,0) */ /* surrender write-lock */ if (fd != -1) { # ifdef LOCK_UN status = flock(fd, LOCK_UN); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # else /* LOCK_UN */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_UNLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # endif /* LOCK_UN */ } if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); #endif /* USE_DB */ #ifdef USE_MDB mdb = db->db_data; if (db->db_lock != NULL) (void) pthread_mutex_lock(db->db_lock); key.mv_data = outbuf; key.mv_size = outbuflen; data.mv_data = (char *) buf; data.mv_size = (buflen == 0 ? strlen(buf) : buflen); if (mdb_txn_begin(mdb->mdb_env, NULL, 0, &txn) == 0 && mdb_dbi_open(txn, NULL, 0, &dbi) == 0 && mdb_put(txn, dbi, &key, &data, 0) == 0) ret = 0; else ret = -1; if (txn != NULL) { if (ret == 0) mdb_txn_commit(txn); else mdb_txn_abort(txn); } if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); #endif /* USE_MDB */ return ret; } /* ** DKIMF_DB_GET -- retrieve data from an open database ** ** Parameters: ** db -- DB handle to use for searching ** buf -- pointer to the key ** buflen -- length of key (use strlen() if 0) ** req -- list of data requests ** reqnum -- number of data requests ** exists -- pointer to a "_Bool" updated to be TRUE if the record ** was found, FALSE otherwise (may be NULL) ** ** Return value: ** 0 -- operation successful ** !0 -- error occurred; error code returned ** ** Notes: ** "req" references a caller-provided array of DKIMF_DBDATA ** structures that describe the name of the attribute wanted, ** the location to which to write the data, and how big that buffer is. ** On completion, any found attributes will have their lengths ** set to the number of bytes retrieved and the data will be copied ** up to the limit (if more data was retrieved than the space available, ** the available space will be filled but the returned length will be ** longer); any not-found attributes will leave the buffers unchanged ** and the lengths will be set to (unsigned int) -1. ** ** For LDAP queries, the attribute name is used as the LDAP attribute ** name in the request. ** ** For SQL queries, the attribute name is not used; columns are specified ** in the DSN (see dkimf_db_open() above), and are copied into the ** request in order. ** ** For backward compatibility, text values in the other databases ** that are colon-delimited will be parsed as such, and the requested ** values will be filled in in order (so for "aaa:bbb", "aaa" will be ** copied into the first attribute, "bbb" will be copied to the second, ** and all others will receive no data. */ int dkimf_db_get(DKIMF_DB db, void *buf, size_t buflen, DKIMF_DBDATA req, unsigned int reqnum, _Bool *exists) { _Bool matched; assert(db != NULL); assert(buf != NULL); assert(req != NULL || reqnum == 0); /* ** Indicate "not found" if we require ASCII-only and there was ** non-ASCII in the query. */ if ((db->db_flags & DKIMF_DB_FLAG_ASCIIONLY) != 0) { char *p; char *end; end = (char *) buf + buflen; for (p = (char *) buf; p <= end; p++) { if (!isascii(*p)) { if (*exists) *exists = FALSE; return 0; } } } switch (db->db_type) { case DKIMF_DB_TYPE_FILE: case DKIMF_DB_TYPE_CSL: { struct dkimf_db_list *list; for (list = (struct dkimf_db_list *) db->db_handle; list != NULL; list = list->db_list_next) { matched = FALSE; if ((db->db_flags & DKIMF_DB_FLAG_ICASE) == 0) { if (strcmp(buf, list->db_list_key) == 0) matched = TRUE; } else { if (strcasecmp(buf, list->db_list_key) == 0) matched = TRUE; } if (!matched) continue; if ((db->db_flags & DKIMF_DB_FLAG_MATCHBOTH) == 0 || reqnum == 0 || list->db_list_value == NULL) break; matched = FALSE; assert(list->db_list_value != NULL); if ((db->db_flags & DKIMF_DB_FLAG_ICASE) == 0) { if (strncmp(req[0].dbdata_buffer, list->db_list_value, req[0].dbdata_buflen) == 0) matched = TRUE; } else { if (strncasecmp(req[0].dbdata_buffer, list->db_list_value, req[0].dbdata_buflen) == 0) matched = TRUE; } if (matched) break; } if (list == NULL) { if (exists != NULL) *exists = FALSE; } else { if (exists != NULL) *exists = TRUE; if (list->db_list_value != NULL && reqnum != 0) { if (dkimf_db_datasplit(list->db_list_value, strlen(list->db_list_value), req, reqnum) != 0) return -1; } } return 0; } case DKIMF_DB_TYPE_REFILE: { struct dkimf_db_relist *list; list = (struct dkimf_db_relist *) db->db_handle; while (list != NULL) { if (regexec(&list->db_relist_re, buf, 0, NULL, 0) == 0) { if (exists != NULL) *exists = TRUE; if (reqnum != 0 && list->db_relist_data != NULL) { if (dkimf_db_datasplit(list->db_relist_data, strlen(list->db_relist_data), req, reqnum) != 0) return -1; } return 0; } list = list->db_relist_next; } if (exists != NULL) *exists = FALSE; return 0; } #ifdef USE_DB case DKIMF_DB_TYPE_BDB: { int ret; int status; int fd; DB *bdb; DBT d; DBT q; char databuf[BUFRSZ + 1]; bdb = (DB *) db->db_handle; memset(&d, 0, sizeof d); memset(&q, 0, sizeof q); q.data = (char *) buf; q.size = (buflen == 0 ? strlen(q.data) : buflen); ret = 0; # if DB_VERSION_CHECK(2,0,0) d.flags = DB_DBT_USERMEM; d.ulen = BUFRSZ; # endif /* DB_VERSION_CHECK(2,0,0) */ d.data = databuf; d.size = BUFRSZ; memset(databuf, '\0', sizeof databuf); /* establish read-lock */ fd = -1; status = 0; if ((db->db_flags & DKIMF_DB_FLAG_NOFDLOCK) == 0) { # if DB_VERSION_CHECK(2,0,0) status = bdb->fd(bdb, &fd); # else /* DB_VERSION_CHECK(2,0,0) */ fd = bdb->fd(bdb); # endif /* DB_VERSION_CHECK(2,0,0) */ } /* single-thread readers since we can only lock the DB once */ if (db->db_lock != NULL) (void) pthread_mutex_lock(db->db_lock); if (status == 0 && fd != -1) { # ifdef LOCK_SH status = flock(fd, LOCK_SH); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # else /* LOCK_SH */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_RDLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # endif /* LOCK_SH */ } # if DB_VERSION_CHECK(2,0,0) status = bdb->get(bdb, NULL, &q, &d, 0); if (status == 0) { if (exists != NULL) *exists = TRUE; ret = 0; if (reqnum != 0) { ret = dkimf_db_datasplit(databuf, d.size, req, reqnum); } } else if (status == DB_NOTFOUND) { if (exists != NULL) *exists = FALSE; ret = 0; } else { db->db_status = status; ret = status; } # else /* DB_VERSION_CHECK(2,0,0) */ status = bdb->get(bdb, &q, &d, 0); if (status == 1) { if (exists != NULL) *exists = FALSE; ret = 0; } else if (status == 0) { size_t clen; if (exists != NULL) *exists = TRUE; clen = MIN(sizeof databuf - 1, d.size); memset(databuf, '\0', sizeof databuf); memcpy(databuf, d.data, clen); ret = 0; if (reqnum != 0) { ret = dkimf_db_datasplit(databuf, clen, req, reqnum); } } else { db->db_status = errno; ret = errno; } # endif /* DB_VERSION_CHECK(2,0,0) */ /* surrender read-lock */ if (fd != -1) { # ifdef LOCK_SH status = flock(fd, LOCK_UN); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # else /* LOCK_SH */ struct flock l; l.l_start = 0; l.l_len = 0; l.l_type = F_UNLCK; l.l_whence = SEEK_SET; status = fcntl(fd, F_SETLKW, &l); if (status != 0) { db->db_status = status; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } # endif /* LOCK_SH */ } if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return ret; } #endif /* USE_DB */ #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: { _Bool reconnected = FALSE; int err; int fields; int rescnt = 0; int rowcnt = 0; u_long elen; odbx_result_t *result; odbx_t *odbx = NULL; struct dkimf_db_dsn *dsn; char query[BUFRSZ]; char escaped[BUFRSZ]; dsn = (struct dkimf_db_dsn *) db->db_data; # ifdef _FFR_DB_HANDLE_POOLS odbx = dkimf_db_hp_get((struct handle_pool *) db->db_handle, &err); if (odbx == NULL) { db->db_status = err; return -1; } # else /* _FFR_DB_HANDLE_POOLS */ if (db->db_lock != NULL) (void) pthread_mutex_lock(db->db_lock); /* see if we need to reopen */ if ((db->db_iflags & DKIMF_DB_IFLAG_RECONNECT) != 0) { err = dkimf_db_open_sql(dsn, (odbx_t **) &db->db_handle, NULL); if (err < 0) { db->db_status = err; return -1; } reconnected = TRUE; db->db_iflags &= ~DKIMF_DB_IFLAG_RECONNECT; } odbx = (odbx_t *) db->db_handle; # endif /* _FFR_DB_HANDLE_POOLS */ memset(escaped, '\0', sizeof escaped); elen = sizeof escaped - 1; err = odbx_escape(odbx, buf, (buflen == 0 ? strlen(buf) : buflen), escaped, &elen); if (err < 0) { db->db_status = err; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return err; } snprintf(query, sizeof query, "SELECT %s FROM %s WHERE %s = '%s'%s%s", dsn->dsn_datacol, dsn->dsn_table, dsn->dsn_keycol, escaped, dsn->dsn_filter == NULL ? "" : " AND ", dsn->dsn_filter == NULL ? "" : dsn->dsn_filter); err = odbx_query(odbx, query, 0); if (err < 0) { int status; db->db_status = err; if (reconnected) { if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return err; } status = odbx_error_type(odbx, err); #ifdef _FFR_POSTGRESQL_RECONNECT_HACK if (status >= 0) { const char *estr; estr = odbx_error(odbx, db->db_status); if (estr != NULL && strncmp(estr, "FATAL:", 6) == 0) status = -1; } #endif /* _FFR_POSTGRESQL_RECONNECT_HACK */ if (status < 0) { (void) odbx_unbind(odbx); (void) odbx_finish(odbx); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_dead((struct handle_pool *) db->db_handle); # else /* _FFR_DB_HANDLE_POOLS */ db->db_iflags |= DKIMF_DB_IFLAG_RECONNECT; # endif /* _FFR_DB_HANDLE_POOLS */ if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return dkimf_db_get(db, buf, buflen, req, reqnum, exists); } else { if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return err; } } for (rescnt = 0; ; rescnt++) { err = odbx_result(odbx, &result, NULL, 0); if (err < 0) { int status; db->db_status = err; if (reconnected) { if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return err; } status = odbx_error_type(odbx, err); #ifdef _FFR_POSTGRESQL_RECONNECT_HACK if (status >= 0) { const char *estr; estr = odbx_error(odbx, db->db_status); if (estr != NULL && strncmp(estr, "FATAL:", 6) == 0) status = -1; } #endif /* _FFR_POSTGRESQL_RECONNECT_HACK */ if (result != NULL) (void) odbx_result_finish(result); if (status < 0) { (void) odbx_unbind(odbx); (void) odbx_finish(odbx); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_dead((struct handle_pool *) db->db_handle); # else /* _FFR_DB_HANDLE_POOLS */ db->db_iflags |= DKIMF_DB_IFLAG_RECONNECT; # endif /* _FFR_DB_HANDLE_POOLS */ if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return dkimf_db_get(db, buf, buflen, req, reqnum, exists); } if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return err; } else if (err == ODBX_RES_DONE) { if (exists != NULL && rescnt == 0) *exists = FALSE; err = odbx_result_finish(result); if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return 0; } for (rowcnt = 0; ; rowcnt++) { err = odbx_row_fetch(result); if (err < 0) { db->db_status = err; err = odbx_result_finish(result); if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return db->db_status; } else if (err == ODBX_RES_DONE) { if (exists != NULL && rescnt == 0 && rowcnt == 0) *exists = FALSE; break; } /* only copy out the first hit */ if (rescnt == 0 && rowcnt == 0) { fields = odbx_column_count(result); if (fields == 0) continue; if (exists != NULL) *exists = TRUE; if (reqnum != 0) { int c; for (c = 0; c < reqnum; c++) { if (c >= fields) { req[c].dbdata_buflen = 0; } else { char *val; val = (char *) odbx_field_value(result, c); if (val == NULL) { req[c].dbdata_buflen = 0; } else { req[c].dbdata_buflen = strlcpy(req[c].dbdata_buffer, val, req[c].dbdata_buflen); } } } } } } err = odbx_result_finish(result); } if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_put((struct handle_pool *) db->db_handle, (void *) odbx); # endif /* _FFR_DB_HANDLE_POOLS */ return 0; } #endif /* USE_ODBX */ #ifdef USE_LDAP case DKIMF_DB_TYPE_LDAP: { int c; int status; LDAP *ld; LDAPMessage *result; LDAPMessage *e; struct dkimf_db_ldap *ldap; #ifdef _FFR_LDAP_CACHING # ifdef USE_DB struct dkimf_db_ldap_cache *ldc = NULL; # endif /* USE_DB */ #endif /* _FFR_LDAP_CACHING */ struct berval **vals; char query[BUFRSZ]; char filter[BUFRSZ]; struct timeval timeout; ld = (LDAP *) db->db_handle; ldap = (struct dkimf_db_ldap *) db->db_data; pthread_mutex_lock(&ldap->ldap_lock); if (ld == NULL) { int lderr; lderr = dkimf_db_open_ldap(&ld, ldap, NULL); if (lderr == LDAP_SUCCESS) { db->db_handle = ld; } else { db->db_status = lderr; pthread_mutex_unlock(&ldap->ldap_lock); return lderr; } } #ifdef _FFR_LDAP_CACHING # ifdef USE_DB if (ldap->ldap_cache != NULL) { _Bool cex = FALSE; struct dkimf_db_data dbd; dbd.dbdata_buffer = (char *) &ldc; dbd.dbdata_buflen = sizeof ldc; dbd.dbdata_flags = DKIMF_DB_DATA_BINARY; status = dkimf_db_get(ldap->ldap_cache, buf, buflen, &dbd, 1, &cex); if (cex) { struct timeval now; (void) gettimeofday(&now, NULL); if (ldc->ldc_state == DKIMF_DB_CACHE_DATA && ldc->ldc_absent) { if (exists != NULL) *exists = FALSE; pthread_mutex_unlock(&ldap->ldap_lock); return 0; } else if (ldc->ldc_state == DKIMF_DB_CACHE_DATA && ldc->ldc_expire <= now.tv_sec) { ldc->ldc_state = DKIMF_DB_CACHE_PENDING; } else if (ldc->ldc_state == DKIMF_DB_CACHE_DATA && ldc->ldc_error != 0) { pthread_mutex_unlock(&ldap->ldap_lock); return ldc->ldc_error; } else if (ldc->ldc_state == DKIMF_DB_CACHE_DATA && ldc->ldc_expire > now.tv_sec) { if (exists != NULL) *exists = TRUE; for (c = 0; c < reqnum && c < ldc->ldc_nresults; c++) { req[c].dbdata_buflen = strlcpy(req[c].dbdata_buffer, ldc->ldc_results[c], req[c].dbdata_buflen); } while (c < reqnum) req[c++].dbdata_buflen = 0; pthread_mutex_unlock(&ldap->ldap_lock); return 0; } else if (ldc->ldc_state == DKIMF_DB_CACHE_PENDING) { struct timespec timeout; timeout.tv_sec = now.tv_sec + ldap->ldap_timeout; timeout.tv_nsec = now.tv_usec * 1000; ldc->ldc_waiters++; while (ldc->ldc_state == DKIMF_DB_CACHE_PENDING) { status = pthread_cond_timedwait(&ldc->ldc_cond, &ldap->ldap_lock, &timeout); if (status != 0) { pthread_mutex_unlock(&ldap->ldap_lock); return status; } } if (ldc->ldc_error != 0) { pthread_mutex_unlock(&ldap->ldap_lock); return ldc->ldc_error; } if (ldc->ldc_absent) { if (exists != NULL) *exists = FALSE; pthread_mutex_unlock(&ldap->ldap_lock); return 0; } for (c = 0; c < reqnum && c < ldc->ldc_nresults; c++) { req[c].dbdata_buflen = strlcpy(req[c].dbdata_buffer, ldc->ldc_results[c], req[c].dbdata_buflen); } while (c < reqnum) req[c++].dbdata_buflen = 0; ldc->ldc_waiters--; pthread_cond_signal(&ldc->ldc_cond); pthread_mutex_unlock(&ldap->ldap_lock); return 0; } } /* add pending info to cache */ if (ldc == NULL) { ldc = malloc(sizeof *ldc); if (ldc == NULL) { pthread_mutex_unlock(&ldap->ldap_lock); return errno; } memset(ldc, '\0', sizeof *ldc); pthread_cond_init(&ldc->ldc_cond, NULL); ldc->ldc_state = DKIMF_DB_CACHE_PENDING; status = dkimf_db_put(ldap->ldap_cache, buf, buflen, &ldc, sizeof ldc); if (status != 0) { pthread_mutex_unlock(&ldap->ldap_lock); return status; } } /* unlock so others can try */ pthread_mutex_unlock(&ldap->ldap_lock); ldc->ldc_error = 0; } # endif /* USE_DB */ #endif /* _FFR_LDAP_CACHING */ memset(query, '\0', sizeof query); memset(filter, '\0', sizeof filter); dkimf_db_mkldapquery(ldap->ldap_descr->lud_dn, buf, FALSE, query, sizeof query); if (ldap->ldap_descr->lud_filter != NULL) { dkimf_db_mkldapquery(ldap->ldap_descr->lud_filter, buf, FALSE, filter, sizeof filter); } timeout.tv_sec = ldap->ldap_timeout; timeout.tv_usec = 0; status = ldap_search_ext_s(ld, query, ldap->ldap_descr->lud_scope, filter, ldap->ldap_descr->lud_attrs, 0, NULL, NULL, &timeout, 0, &result); if (LDAP_NAME_ERROR(status)) { if (exists != NULL) *exists = FALSE; #ifdef _FFR_LDAP_CACHING # ifdef USE_DB ldc->ldc_absent = TRUE; ldc->ldc_state = DKIMF_DB_CACHE_DATA; pthread_cond_broadcast(&ldc->ldc_cond); # endif /* USE_DB */ #endif /* _FFR_LDAP_CACHING */ pthread_mutex_unlock(&ldap->ldap_lock); return 0; } else if (status == LDAP_SERVER_DOWN || status == LDAP_TIMEOUT) { ldap_unbind_ext(ld, NULL, NULL); db->db_handle = NULL; if ((db->db_iflags & DKIMF_DB_IFLAG_RECONNECT) != 0) { db->db_status = status; pthread_mutex_unlock(&ldap->ldap_lock); return -1; } db->db_iflags |= DKIMF_DB_IFLAG_RECONNECT; pthread_mutex_unlock(&ldap->ldap_lock); status = dkimf_db_get(db, buf, buflen, req, reqnum, exists); db->db_iflags &= ~DKIMF_DB_IFLAG_RECONNECT; return status; } else if (status != LDAP_SUCCESS) { db->db_status = status; #ifdef _FFR_LDAP_CACHING # ifdef USE_DB ldc->ldc_error = status; ldc->ldc_expire = time(NULL) + DKIMF_LDAP_TTL; ldc->ldc_state = DKIMF_DB_CACHE_DATA; pthread_cond_broadcast(&ldc->ldc_cond); # endif /* USE_DB */ #endif /* _FFR_LDAP_CACHING */ pthread_mutex_unlock(&ldap->ldap_lock); return status; } e = NULL; if (result != NULL) e = ldap_first_entry(ld, result); if (e == NULL) { if (exists != NULL) *exists = FALSE; #ifdef _FFR_LDAP_CACHING # ifdef USE_DB ldc->ldc_absent = TRUE; ldc->ldc_state = DKIMF_DB_CACHE_DATA; pthread_cond_broadcast(&ldc->ldc_cond); # endif /* USE_DB */ #endif /* _FFR_LDAP_CACHING */ pthread_mutex_unlock(&ldap->ldap_lock); ldap_msgfree(result); return 0; } if (exists != NULL) *exists = TRUE; for (c = 0; c < reqnum; c++) { /* bail if we're out of attributes */ if (ldap->ldap_descr->lud_attrs[c] == NULL) break; vals = ldap_get_values_len(ld, e, ldap->ldap_descr->lud_attrs[c]); if (vals != NULL && vals[0] != NULL) { size_t clen; clen = MIN(req[c].dbdata_buflen, vals[0]->bv_len); memcpy(req[c].dbdata_buffer, vals[0]->bv_val, clen); clen = MAX(req[c].dbdata_buflen, vals[0]->bv_len); req[c].dbdata_buflen = clen; ldap_value_free_len(vals); } } /* tag requests that weren't fulfilled */ while (c < reqnum) req[c++].dbdata_buflen = 0; ldap_msgfree(result); # ifdef _FFR_LDAP_CACHING # ifdef USE_DB pthread_mutex_lock(&ldap->ldap_lock); /* flush anything already cached */ if (ldc->ldc_nresults != 0) { for (c = 0; c < ldc->ldc_nresults; c++) free(ldc->ldc_results[c]); free(ldc->ldc_results); } /* cache results */ ldc->ldc_results = malloc(sizeof(char *) * reqnum); if (ldc->ldc_results == NULL) { ldc->ldc_error = errno; ldc->ldc_expire = time(NULL) + DKIMF_LDAP_TTL; ldc->ldc_state = DKIMF_DB_CACHE_DATA; pthread_mutex_unlock(&ldap->ldap_lock); return errno; } ldc->ldc_nresults = reqnum; for (c = 0; c < reqnum; c++) { ldc->ldc_results[c] = strdup(req[c].dbdata_buffer); if (ldc->ldc_results[c] == NULL) { ldc->ldc_error = errno; pthread_mutex_unlock(&ldap->ldap_lock); return errno; } } ldc->ldc_state = DKIMF_DB_CACHE_DATA; ldc->ldc_expire = time(NULL) + DKIMF_LDAP_TTL; /* notify waiters */ pthread_cond_broadcast(&ldc->ldc_cond); # endif /* USE_DB */ # endif /* _FFR_LDAP_CACHING */ pthread_mutex_unlock(&ldap->ldap_lock); return 0; } #endif /* USE_LDAP */ #ifdef USE_LUA case DKIMF_DB_TYPE_LUA: { int c; int status; struct dkimf_db_lua *lua; struct dkimf_lua_script_result lres; memset(&lres, '\0', sizeof lres); lua = (struct dkimf_db_lua *) db->db_data; status = dkimf_lua_db_hook((const char *) lua->lua_script, lua->lua_scriptlen, (const char *) buf, &lres, NULL, NULL); if (status != 0) return -1; if (exists != NULL) *exists = (lres.lrs_rcount != 0); /* copy results */ for (c = 0; c < reqnum && c < lres.lrs_rcount; c++) { req[c].dbdata_buflen = strlcpy(req[c].dbdata_buffer, lres.lrs_results[c], req[c].dbdata_buflen); } /* tag requests that weren't fulfilled */ while (c < reqnum) req[c++].dbdata_buflen = 0; /* clean up */ for (c = 0; c < lres.lrs_rcount; c++) free(lres.lrs_results[c]); if (lres.lrs_results != NULL) free(lres.lrs_results); return 0; } #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED case DKIMF_DB_TYPE_MEMCACHE: { memcached_st *mcs; memcached_return_t ret; char *out; char *key; size_t vlen; uint32_t flags; char query[BUFRSZ + 1]; mcs = (memcached_st *) db->db_handle; key = (char *) db->db_data; snprintf(query, sizeof query, "%s:%s", key, (char *) buf); out = memcached_get(mcs, query, strlen(query), &vlen, &flags, &ret); if (out != NULL) { if (exists != NULL) *exists = TRUE; if (dkimf_db_datasplit(out, vlen, req, reqnum) != 0) { free(out); return -1; } free(out); return 0; } else if (ret == MEMCACHED_NOTFOUND) { if (exists != NULL) *exists = FALSE; return 0; } else { db->db_status = (int) ret; return -1; } } #endif /* USE_LIBMEMCACHED */ #ifdef _FFR_REPUTATION case DKIMF_DB_TYPE_REPUTE: { _Bool found = FALSE; int c; float rep; float conf; unsigned long samp; unsigned long limit; time_t when; REPUTE_STAT rstat; REPUTE r; r = (REPUTE) db->db_data; if (!found) { rstat = repute_query(r, (char *) buf, &rep, &conf, &samp, &limit, &when); if (rstat == REPUTE_STAT_PARSE) return 0; else if (rstat != REPUTE_STAT_OK) return -1; if (exists != NULL) *exists = TRUE; } if (reqnum >= 1 && req[0].dbdata_buffer != NULL && req[0].dbdata_buflen != 0) { if ((req[0].dbdata_flags & DKIMF_DB_DATA_BINARY) != 0) { if (req[0].dbdata_buflen != sizeof rep) return -1; memcpy(req[0].dbdata_buffer, &rep, sizeof rep); } else { req[0].dbdata_buflen = snprintf(req[0].dbdata_buffer, req[0].dbdata_buflen, "%f", rep); } } if (reqnum >= 2 && req[1].dbdata_buffer != NULL && req[1].dbdata_buflen != 0) { if ((req[1].dbdata_flags & DKIMF_DB_DATA_BINARY) != 0) { if (req[1].dbdata_buflen != sizeof conf) return -1; memcpy(req[1].dbdata_buffer, &conf, sizeof conf); } else { req[1].dbdata_buflen = snprintf(req[1].dbdata_buffer, req[1].dbdata_buflen, "%f", conf); } } if (reqnum >= 3 && req[2].dbdata_buffer != NULL && req[2].dbdata_buflen != 0) { if ((req[2].dbdata_flags & DKIMF_DB_DATA_BINARY) != 0) { if (req[2].dbdata_buflen != sizeof samp) return -1; memcpy(req[2].dbdata_buffer, &samp, sizeof samp); } else { req[2].dbdata_buflen = snprintf(req[2].dbdata_buffer, req[2].dbdata_buflen, "%lu", samp); } } if (reqnum >= 4 && req[3].dbdata_buffer != NULL && req[3].dbdata_buflen != 0) { if ((req[3].dbdata_flags & DKIMF_DB_DATA_BINARY) != 0) { if (req[3].dbdata_buflen != sizeof when) return -1; memcpy(req[3].dbdata_buffer, &when, sizeof when); } else { req[3].dbdata_buflen = snprintf(req[3].dbdata_buffer, req[3].dbdata_buflen, "%lu", when); } } if (reqnum >= 5 && req[4].dbdata_buffer != NULL && req[4].dbdata_buflen != 0) { if ((req[4].dbdata_flags & DKIMF_DB_DATA_BINARY) != 0) { if (req[4].dbdata_buflen != sizeof limit) return -1; memcpy(req[4].dbdata_buffer, &limit, sizeof limit); } else { req[4].dbdata_buflen = snprintf(req[4].dbdata_buffer, req[4].dbdata_buflen, "%lu", limit); } } /* tag requests that weren't fulfilled */ for (c = 5; c < reqnum; c++) req[c].dbdata_buflen = 0; return 0; } #endif /* _FFR_REPUTATION */ #ifdef _FFR_SOCKETDB case DKIMF_DB_TYPE_SOCKET: { int status; size_t len; size_t wlen; fd_set rfds; struct timeval timeout; struct iovec iov[2]; struct dkimf_db_socket *sdb; char *tmp; char inbuf[BUFRSZ]; sdb = (struct dkimf_db_socket *) db->db_handle; timeout.tv_sec = DKIMF_SOCKET_TIMEOUT; timeout.tv_usec = 0; iov[0].iov_base = buf; iov[0].iov_len = buflen; iov[1].iov_base = "\n"; iov[1].iov_len = 1; /* single-thread readers */ if (db->db_lock != NULL) (void) pthread_mutex_lock(db->db_lock); wlen = writev(sdb->sockdb_fd, iov, 2); if (wlen < buflen + 1) { db->db_status = errno; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } FD_ZERO(&rfds); FD_SET(sdb->sockdb_fd, &rfds); dkimf_dstring_blank(sdb->sockdb_buf); for (;;) { status = select(sdb->sockdb_fd + 1, &rfds, NULL, NULL, &timeout); if (status != 1) { db->db_status = errno; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } wlen = read(sdb->sockdb_fd, inbuf, sizeof inbuf); if (wlen == (size_t) -1) { db->db_status = errno; if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } if (wlen == 0) break; dkimf_dstring_catn(sdb->sockdb_buf, inbuf, wlen); tmp = dkimf_dstring_get(sdb->sockdb_buf); len = dkimf_dstring_len(sdb->sockdb_buf); if (tmp[len - 1] == '\n') break; } if (len > 0 && exists != NULL) *exists = TRUE; if (dkimf_db_datasplit(tmp, len - 1, req, reqnum) != 0) { if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return -1; } else { if (db->db_lock != NULL) (void) pthread_mutex_unlock(db->db_lock); return 0; } } #endif /* _FFR_SOCKETDB */ #ifdef USE_MDB case DKIMF_DB_TYPE_MDB: { int status; struct dkimf_db_mdb *mdb; MDB_val key; MDB_val data; mdb = (struct dkimf_db_mdb *) db->db_handle; key.mv_size = buflen; key.mv_data = buf; status = mdb_get(mdb->mdb_txn, mdb->mdb_dbi, &key, &data); if (status == MDB_NOTFOUND) { if (exists != NULL) *exists = FALSE; } else if (status == 0) { if (exists != NULL) *exists = TRUE; if (dkimf_db_datasplit(data.mv_data, data.mv_size, req, reqnum) != 0) return -1; } else { db->db_status = status; return -1; } return 0; } #endif /* USE_MDB */ #ifdef USE_ERLANG case DKIMF_DB_TYPE_ERLANG: { int fd; int ret; int res_size; int res_index; int res_type; struct dkimf_db_erlang *e; ei_cnode ec; ei_x_buff args; ei_x_buff resp; e = (struct dkimf_db_erlang *) db->db_data; ei_x_new(&args); ei_x_new(&resp); ei_x_encode_list_header(&args, 1); ei_x_encode_binary(&args, buf, strlen(buf)); ei_x_encode_empty_list(&args); fd = dkimf_db_erl_connect(db, &ec); if (fd < 0) { db->db_status = erl_errno; ei_x_free(&args); ei_x_free(&resp); return -1; } ret = ei_rpc(&ec, fd, e->erlang_module, e->erlang_function, args.buff, args.index, &resp); close(fd); if (ret == -1) { db->db_status = erl_errno; ei_x_free(&args); ei_x_free(&resp); return ret; } ret = dkimf_db_erl_decode_response(&resp, "not_found", req, reqnum, NULL, NULL); if (exists != NULL) { if (ret == 1) *exists = FALSE; else if (ret == 0) *exists = TRUE; } ei_x_free(&args); ei_x_free(&resp); if (ret == -1) db->db_status = erl_errno; return 0; } #endif /* USE_ERLANG */ default: assert(0); return 0; /* to silence the compiler */ } /* NOTREACHED */ } /* ** DKIMF_DB_CLOSE -- close a DB handle ** ** Parameters: ** db -- DB handle to shut down ** ** Return value: ** 0 on success, something else on failure ** ** Notes: ** On failure, db has not been freed. It's not clear what to do in ** that case other than get very upset because we probably have a ** descriptor that can't be closed. The subsystem involved should ** probably disable itself or otherwise attract attention. */ int dkimf_db_close(DKIMF_DB db) { assert(db != NULL); if (db->db_array != NULL) { int c; if ((db->db_iflags & DKIMF_DB_IFLAG_FREEARRAY) != 0) { for (c = 0; db->db_array[c] != NULL; c++) free(db->db_array[c]); } free(db->db_array); db->db_array = NULL; } if (db->db_lock != NULL && (db->db_flags & DKIMF_DB_FLAG_MAKELOCK) != 0) { pthread_mutex_destroy(db->db_lock); free(db->db_lock); } switch (db->db_type) { case DKIMF_DB_TYPE_FILE: case DKIMF_DB_TYPE_CSL: if (db->db_handle != NULL) dkimf_db_list_free(db->db_handle); free(db); return 0; case DKIMF_DB_TYPE_REFILE: if (db->db_handle != NULL) dkimf_db_relist_free(db->db_handle); free(db); return 0; #ifdef USE_DB case DKIMF_DB_TYPE_BDB: { int status; # if DB_VERSION_CHECK(2,0,0) if (db->db_cursor != NULL) ((DBC *) (db->db_cursor))->c_close((DBC *) db->db_cursor); # endif /* DB_VERSION_CHECK(2,0,0) */ status = DKIMF_DBCLOSE((DB *) (db->db_handle)); if (status != 0) db->db_status = status; else free(db); return status; } #endif /* USE_DB */ #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: # ifdef _FFR_DB_HANDLE_POOLS dkimf_db_hp_free((struct handle_pool *) db->db_handle); # else /* _FFR_DB_HANDLE_POOLS */ (void) odbx_finish((odbx_t *) db->db_handle); # endif /* _FFR_DB_HANDLE_POOLS */ free(db->db_data); free(db); return 0; #endif /* USE_ODBX */ #ifdef USE_LDAP case DKIMF_DB_TYPE_LDAP: { struct dkimf_db_ldap *ldap; ldap = (struct dkimf_db_ldap *) db->db_data; ldap_unbind_ext((LDAP *) db->db_handle, NULL, NULL); pthread_mutex_destroy(&ldap->ldap_lock); # ifdef _FFR_LDAP_CACHING # ifdef USE_DB if (ldap->ldap_cache != NULL) { _Bool first = TRUE; int c; int status; struct dkimf_db_ldap_cache *ldc; struct dkimf_db_data dbd; dbd.dbdata_buffer = (char *) &ldc; dbd.dbdata_buflen = sizeof ldc; dbd.dbdata_flags = DKIMF_DB_DATA_BINARY; for (;;) { status = dkimf_db_walk(ldap->ldap_cache, first, NULL, NULL, &dbd, 1); if (status != 0) break; for (c = 0; c < ldc->ldc_nresults; c++) free(ldc->ldc_results[c]); free(ldc->ldc_results); free(ldc); first = FALSE; } (void) dkimf_db_close(ldap->ldap_cache); } # endif /* USE_DB */ # endif /* _FFR_LDAP_CACHING */ (void) ldap_free_urldesc(ldap->ldap_descr); free(db->db_data); free(db); return 0; } #endif /* USE_LDAP */ #ifdef USE_LUA case DKIMF_DB_TYPE_LUA: { struct dkimf_db_lua *lua; lua = (struct dkimf_db_lua *) db->db_data; free(lua->lua_script); free(db->db_data); free(db); return 0; } #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED case DKIMF_DB_TYPE_MEMCACHE: { memcached_st *mcs; mcs = (memcached_st *) db->db_handle; memcached_free(mcs); free(db->db_data); return 0; } #endif /* USE_LIBMEMCACHED */ #ifdef _FFR_REPUTATION case DKIMF_DB_TYPE_REPUTE: { repute_close(db->db_data); free(db); return 0; } #endif /* _FFR_REPUTATION */ #ifdef _FFR_SOCKETDB case DKIMF_DB_TYPE_SOCKET: if (db->db_handle != NULL) { struct dkimf_db_socket *sdb; sdb = (struct dkimf_db_socket *) db->db_handle; close(sdb->sockdb_fd); } free(db); return 0; #endif /* _FFR_SOCKETDB */ #ifdef USE_MDB case DKIMF_DB_TYPE_MDB: { struct dkimf_db_mdb *mdb; mdb = db->db_data; if (db->db_cursor != NULL) mdb_cursor_close(db->db_cursor); mdb_txn_abort(mdb->mdb_txn); mdb_env_close(mdb->mdb_env); free(db->db_data); free(db); return 0; } #endif /* USE_MDB */ #ifdef USE_ERLANG case DKIMF_DB_TYPE_ERLANG: { struct dkimf_db_erlang *e; e = (struct dkimf_db_erlang *) db->db_data; dkimf_db_erl_free(e); return 0; } #endif /* USE_ERLANG */ default: assert(0); return -1; } } /* ** DKIMF_DB_STRERROR -- obtain an error string ** ** Parameters: ** db -- DKIMF_DB handle of interest ** err -- error buffer ** errlen -- bytes available at "err" ** ** Return value: ** Bytes written to "err". */ int dkimf_db_strerror(DKIMF_DB db, char *err, size_t errlen) { assert(db != NULL); assert(err != NULL); switch (db->db_type) { case DKIMF_DB_TYPE_FILE: case DKIMF_DB_TYPE_CSL: case DKIMF_DB_TYPE_SOCKET: return strlcpy(err, strerror(db->db_status), errlen); case DKIMF_DB_TYPE_REFILE: return regerror(db->db_status, db->db_data, err, errlen); #ifdef USE_DB case DKIMF_DB_TYPE_BDB: return strlcpy(err, DB_STRERROR(db->db_status), errlen); #endif /* USE_DB */ #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: { char *p; strlcpy(err, odbx_error((odbx_t *) db->db_handle, db->db_status), errlen); for (p = err + strlen(err) - 1; p >= err; p--) { if (*p == '\n') *p = '\0'; else break; } return strlen(err) + 1; } #endif /* USE_ODBX */ #ifdef USE_LDAP case DKIMF_DB_TYPE_LDAP: return strlcpy(err, ldap_err2string(db->db_status), errlen); #endif /* USE_LDAP */ #ifdef USE_LUA case DKIMF_DB_TYPE_LUA: { struct dkimf_db_lua *lua; lua = (struct dkimf_db_lua *) db->db_data; if (lua->lua_error != NULL) return strlcpy(err, lua->lua_error, errlen); else return 0; } #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED case DKIMF_DB_TYPE_MEMCACHE: return strlcpy(err, memcached_strerror((memcached_st *) db->db_handle, db->db_status), errlen); #endif /* USE_LIBMEMCACHED */ #ifdef _FFR_REPUTATION case DKIMF_DB_TYPE_REPUTE: { REPUTE rep; rep = (REPUTE) db->db_data; return strlcpy(err, repute_error(rep), errlen); } #endif /* _FFR_REPUTATION */ #ifdef USE_MDB case DKIMF_DB_TYPE_MDB: return strlcpy(err, mdb_strerror(db->db_status), errlen); #endif /* USE_MDB */ #ifdef USE_ERLANG case DKIMF_DB_TYPE_ERLANG: return strlcpy(err, strerror(db->db_status), errlen); #endif /* USE_ERLANG */ default: assert(0); return -1; /* to silence the compiler */ } /* NOTREACHED */ } /* ** DKIMF_DB_WALK -- walk a database ** ** Parameters: ** db -- database ** first -- get first record? ** key -- buffer to receive the key ** keylen -- bytes available at "key" (updated) ** req -- buffers to receive the data ("requests") ** reqnum -- number of requests ** ** Return value: ** 0 -- record returned ** 1 -- no more records ** -1 -- error */ int dkimf_db_walk(DKIMF_DB db, _Bool first, void *key, size_t *keylen, DKIMF_DBDATA req, unsigned int reqnum) { assert(db != NULL); if ((key != NULL && keylen == NULL) || (key == NULL && keylen != NULL)) return -1; if (db->db_type == DKIMF_DB_TYPE_REFILE || db->db_type == DKIMF_DB_TYPE_SOCKET || db->db_type == DKIMF_DB_TYPE_LUA) return -1; switch (db->db_type) { case DKIMF_DB_TYPE_CSL: case DKIMF_DB_TYPE_FILE: { struct dkimf_db_list *list; if (first) list = (struct dkimf_db_list *) db->db_handle; else list = (struct dkimf_db_list *) db->db_cursor; if (list == NULL) return 1; if (key != NULL) *keylen = strlcpy(key, list->db_list_key, *keylen); if (reqnum != 0) { if (list->db_list_value != NULL) { if (dkimf_db_datasplit(list->db_list_value, strlen(list->db_list_value), req, reqnum) != 0) return -1; } } list = list->db_list_next; db->db_cursor = list; return 0; } #ifdef USE_DB case DKIMF_DB_TYPE_BDB: { int status = 0; DB *bdb; DBT k; DBT d; # if DB_VERSION_CHECK(2,0,0) DBC *dbc; # endif /* DB_VERSION_CHECK(2,0,0) */ char databuf[BUFRSZ + 1]; bdb = (DB *) db->db_handle; # if DB_VERSION_CHECK(2,0,0) /* establish a cursor if needed */ dbc = db->db_cursor; if (dbc == NULL) { status = bdb->cursor(bdb, NULL, &dbc, 0); if (status != 0) { db->db_status = status; return -1; } db->db_cursor = dbc; } # endif /* DB_VERSION_CHECK(2,0,0) */ memset(&k, '\0', sizeof k); memset(&d, '\0', sizeof d); # if DB_VERSION_CHECK(2,0,0) k.data = (void *) key; k.flags = DB_DBT_USERMEM; k.ulen = (keylen != NULL ? *keylen : 0); # endif /* DB_VERSION_CHECK(2,0,0) */ # if DB_VERSION_CHECK(2,0,0) d.data = databuf; d.flags = DB_DBT_USERMEM; d.ulen = sizeof databuf; # endif /* DB_VERSION_CHECK(2,0,0) */ # if DB_VERSION_CHECK(2,0,0) status = dbc->c_get(dbc, &k, &d, first ? DB_FIRST : DB_NEXT); # else /* DB_VERSION_CHECK(2,0,0) */ status = bdb->seq(bdb, &k, &d, first ? R_FIRST : R_NEXT); # endif /* DB_VERSION_CHECK(2,0,0) */ if (status == DB_NOTFOUND) { return 1; } else if (status != 0) { db->db_status = status; return -1; } else { # if !DB_VERSION_CHECK(2,0,0) if (key != NULL) { memcpy(key, k.data, MIN(k.size, *keylen)); *keylen = MIN(k.size, *keylen); } if (reqnum != 0) { if (dkimf_db_datasplit(d.data, d.size, req, reqnum) != 0) return -1; } # else /* DB_VERSION_CHECK(2,0,0) */ if (reqnum != 0) { if (dkimf_db_datasplit(databuf, sizeof databuf, req, reqnum) != 0) return -1; } if (keylen != NULL) *keylen = k.size; # endif /* DB_VERSION_CHECK(2,0,0) */ return 0; } } #endif /* USE_DB */ #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: { int err; int fields; odbx_result_t *result; struct dkimf_db_dsn *dsn; dsn = (struct dkimf_db_dsn *) db->db_data; result = (odbx_result_t *) db->db_cursor; /* purge old results cursor if known */ if (result != NULL && first) { for (;;) { err = odbx_row_fetch(result); if (err == ODBX_ROW_DONE) break; } (void) odbx_result_finish(result); result = NULL; } /* run a query and start results cursor if needed */ if (result == NULL) { char query[BUFRSZ]; snprintf(query, sizeof query, "SELECT %s,%s FROM %s", dsn->dsn_keycol, dsn->dsn_datacol, dsn->dsn_table); err = odbx_query((odbx_t *) db->db_handle, query, 0); if (err < 0) { db->db_status = err; return -1; } err = odbx_result((odbx_t *) db->db_handle, &result, NULL, 0); if (err < 0) { (void) odbx_result_finish(result); db->db_status = err; return -1; } db->db_cursor = result; } err = odbx_row_fetch(result); if (err < 0) { (void) odbx_result_finish(result); db->db_cursor = NULL; db->db_status = err; return -1; } if (err == ODBX_ROW_DONE) { (void) odbx_result_finish(result); for (;;) { err = odbx_result((odbx_t *) db->db_handle, &result, NULL, 0); if (err == 0) break; (void) odbx_result_finish(result); } db->db_cursor = NULL; return 1; } fields = odbx_column_count(result); if (fields == 0) { /* query returned no columns somehow */ (void) odbx_result_finish(result); db->db_cursor = NULL; return -1; } if (key != NULL && keylen != NULL) { *keylen = strlcpy(key, (char *) odbx_field_value(result, 0), *keylen); } if (reqnum != 0) { int c; for (c = 0; c < reqnum; c++) { if (c >= fields - 1) { req[c].dbdata_buflen = 0; } else { char *val; val = (char *) odbx_field_value(result, c + 1); if (val == NULL) { req[c].dbdata_buflen = 0; } else { req[c].dbdata_buflen = strlcpy(req[c].dbdata_buffer, val, req[c].dbdata_buflen); } } } } return 0; } #endif /* USE_ODBX */ #ifdef USE_LDAP case DKIMF_DB_TYPE_LDAP: { bool noattrs; int c; int status; char *p; LDAP *ld; LDAPMessage *result; LDAPMessage *e; struct dkimf_db_ldap *ldap; struct berval **vals; char filter[BUFRSZ]; char query[BUFRSZ]; struct timeval timeout; ld = (LDAP *) db->db_handle; ldap = (struct dkimf_db_ldap *) db->db_data; result = (LDAPMessage *) db->db_cursor; pthread_mutex_lock(&ldap->ldap_lock); if (ld == NULL) { int lderr; lderr = dkimf_db_open_ldap(&ld, ldap, NULL); if (lderr == LDAP_SUCCESS) { db->db_handle = ld; } else { db->db_status = lderr; pthread_mutex_unlock(&ldap->ldap_lock); return lderr; } } if (first) { if (result != NULL) { ldap_msgfree(result); db->db_cursor = NULL; db->db_entry = NULL; } memset(query, '\0', sizeof query); memset(filter, '\0', sizeof filter); dkimf_db_mkldapquery(ldap->ldap_descr->lud_dn, "", FALSE, query, sizeof query); dkimf_db_mkldapquery(ldap->ldap_descr->lud_filter, "*", TRUE, filter, sizeof filter); timeout.tv_sec = ldap->ldap_timeout; timeout.tv_usec = 0; status = ldap_search_ext_s(ld, query, ldap->ldap_descr->lud_scope, filter, ldap->ldap_descr->lud_attrs, 0, NULL, NULL, &timeout, 0, &result); if (status != LDAP_SUCCESS) { db->db_status = status; pthread_mutex_unlock(&ldap->ldap_lock); return -1; } db->db_cursor = (void *) result; e = ldap_first_entry(ld, result); if (e == NULL) { pthread_mutex_unlock(&ldap->ldap_lock); return 1; } db->db_entry = (void *) e; } else { e = ldap_next_entry(ld, (LDAPMessage *) db->db_entry); if (e == NULL) { pthread_mutex_unlock(&ldap->ldap_lock); return 1; } db->db_entry = (void *) e; } p = ldap_get_dn(ld, e); if (p != NULL) { #if LDAP_API_VERSION < 3001 LDAPDN *dn = NULL; #else /* LDAP_API_VERSION < 3001 */ LDAPDN dn = NULL; #endif /* LDAP_API_VERSION < 3001 */ LDAPRDN rdn = NULL; LDAPAVA *ava = NULL; if (ldap_str2dn(p, &dn, 0) != 0) { ldap_memfree(p); pthread_mutex_unlock(&ldap->ldap_lock); return 1; } if (dn != NULL) { #if LDAP_API_VERSION < 3001 rdn = dn[0][0][0]; #else /* LDAP_API_VERSION < 3001 */ rdn = dn[0]; #endif /* LDAP_API_VERSION < 3001 */ ava = rdn[0]; } if (key != NULL && keylen != NULL && dn != NULL && ava->la_value.bv_len != 0) { *keylen = strlcpy(key, ava->la_value.bv_val, *keylen); } else if (keylen != NULL) { *keylen = 0; } ldap_dnfree(dn); ldap_memfree(p); } noattrs = FALSE; status = 0; for (c = 0; c < reqnum; c++) { if (ldap->ldap_descr->lud_attrs[c] == NULL) noattrs = TRUE; if (noattrs) { if ((req[c].dbdata_flags & DKIMF_DB_DATA_OPTIONAL) == 0) status = -1; req[c].dbdata_buflen = (size_t) -1; continue; } vals = ldap_get_values_len(ld, e, ldap->ldap_descr->lud_attrs[c]); if (vals != NULL && vals[0]->bv_len != 0) { size_t clen; clen = MIN(req[c].dbdata_buflen, vals[0]->bv_len); memcpy(req[c].dbdata_buffer, vals[0]->bv_val, clen); clen = MAX(req[c].dbdata_buflen, vals[0]->bv_len); req[c].dbdata_buflen = clen; ldap_value_free_len(vals); } else { req[c].dbdata_buflen = 0; } } pthread_mutex_unlock(&ldap->ldap_lock); return status; } #endif /* USE_LDAP */ #ifdef USE_MDB case DKIMF_DB_TYPE_MDB: { int status = 0; MDB_val k; MDB_val d; MDB_cursor *dbc; struct dkimf_db_mdb *mdb; char databuf[BUFRSZ + 1]; mdb = (struct dkimf_db_mdb *) db->db_handle; dbc = db->db_cursor; if (dbc == NULL) { status = mdb_cursor_open(mdb->mdb_txn, mdb->mdb_dbi, &dbc); if (status != 0) { db->db_status = status; return -1; } db->db_cursor = dbc; } memset(&k, '\0', sizeof k); memset(&d, '\0', sizeof d); status = mdb_cursor_get(dbc, &k, &d, first ? MDB_FIRST : MDB_NEXT); if (status == MDB_NOTFOUND) { return 1; } else if (status != 0) { db->db_status = status; return -1; } else { memcpy(key, k.mv_data, MIN(k.mv_size, *keylen)); *keylen = MIN(k.mv_size, *keylen); if (reqnum != 0) { if (dkimf_db_datasplit(d.mv_data, d.mv_size, req, reqnum) != 0) return -1; } return 0; } } #endif /* USE_MDB */ #ifdef USE_ERLANG case DKIMF_DB_TYPE_ERLANG: { int ret, fd; char *cursor; struct dkimf_db_erlang *e; ei_cnode ec; ei_x_buff args; ei_x_buff resp; e = (struct dkimf_db_erlang *) db->db_data; cursor = (char *) db->db_cursor; ei_x_new(&args); ei_x_new(&resp); if (!first && cursor == NULL) assert(0); if (first && cursor != NULL) { free(cursor); cursor = NULL; } ei_x_encode_list_header(&args, 1); if (first) { ei_x_encode_atom(&args, "first"); } else { ei_x_encode_tuple_header(&args, 2); ei_x_encode_atom(&args, "next"); ei_x_encode_binary(&args, cursor, strlen(cursor)); } ei_x_encode_empty_list(&args); fd = dkimf_db_erl_connect(db, &ec); if (fd < 0) { ei_x_free(&args); ei_x_free(&resp); return -1; } ret = ei_rpc(&ec, fd, e->erlang_module, e->erlang_function, args.buff, args.index, &resp); close(fd); if (ret == -1) { ei_x_free(&args); ei_x_free(&resp); return -1; } ret = dkimf_db_erl_decode_response(&resp, "$end_of_table", req, reqnum, key, keylen); ei_x_free(&args); ei_x_free(&resp); switch (ret) { case -1: { if (cursor != NULL) free(cursor); return -1; } case 1: { free(cursor); db->db_cursor = NULL; return 1; } case 0: { if (key != NULL && keylen != NULL) { size_t cursize; cursize = *keylen + 1; cursor = malloc(cursize); if (cursor == NULL) return -1; strlcpy(cursor, key, cursize); db->db_cursor = cursor; } return 0; } } assert(cursor != NULL); } #endif /* USE_ERLANG */ default: assert(0); return -1; /* to silence compiler warnings */ } } /* ** DKIMF_DB_MKARRAY_BASE -- make a (char *) array treating the DB as a ** delta to a provided base ** ** Parameters: ** db -- a DKIMF_DB handle ** a -- array (returned) ** base -- base array ** ** Return value: ** Length of the created array, or -1 on error/empty. */ static int dkimf_db_mkarray_base(DKIMF_DB db, char ***a, const char **base) { _Bool found; int c; int status; int nalloc = 0; int nout = 0; int nbase; size_t buflen; char **out = NULL; char buf[BUFRSZ + 1]; assert(db != NULL); assert(a != NULL); /* count base elements */ for (nbase = 0; base[nbase] != NULL; nbase++) continue; /* initialize output array */ nalloc = MAX(nbase, 16); out = (char **) malloc(sizeof(char *) * nalloc); if (out == NULL) return -1; out[0] = NULL; /* copy the base array modulo removals in the DB */ for (c = 0; c < nbase; c++) { memset(buf, '\0', sizeof buf); snprintf(buf, sizeof buf, "-%s", base[c]); found = FALSE; status = dkimf_db_get(db, buf, 0, NULL, 0, &found); if (status != 0) { for (c = 0; c < nout; c++) free(out[c]); free(out); return -1; } if (!found) { if (nout == nalloc - 1) { char **new; new = (char **) realloc(out, sizeof(char *) * (nalloc * 2)); if (new == NULL) { for (c = 0; c < nout; c++) free(out[c]); free(out); return -1; } out = new; nalloc *= 2; } out[nout] = strdup(base[c]); if (out[nout] == NULL) { for (c = 0; c < nout; c++) free(out[c]); free(out); return -1; } nout++; out[nout] = NULL; } } /* now add any in the DB that aren't in the array */ for (c = 0; ; c++) { buflen = sizeof buf - 1; memset(buf, '\0', sizeof buf); status = dkimf_db_walk(db, (c == 0), buf, &buflen, NULL, 0); if (status == -1) { for (c = 0; c < nout; c++) free(out[c]); free(out); return -1; } else if (status == 1) { break; } else if (buf[0] != '+') { continue; } if (nout == nalloc - 1) { char **new; new = (char **) realloc(out, sizeof(char *) * (nalloc * 2)); if (new == NULL) { for (c = 0; c < nout; c++) free(out[c]); free(out); return -1; } out = new; nalloc *= 2; } out[nout] = strdup(&buf[1]); if (out[nout] == NULL) { for (c = 0; c < nout; c++) free(out[c]); free(out); return -1; } nout++; out[nout] = NULL; } *a = out; return nout; } /* ** DKIMF_DB_MKARRAY -- make a (char *) array of DB contents ** ** Parameters: ** db -- a DKIMF_DB handle ** a -- array (returned) ** base -- base array (may be NULL) ** ** Return value: ** Length of the created array, or -1 on error/empty. */ int dkimf_db_mkarray(DKIMF_DB db, char ***a, const char **base) { _Bool found; int status; char **out = NULL; assert(db != NULL); assert(a != NULL); if (db->db_type == DKIMF_DB_TYPE_REFILE || db->db_type == DKIMF_DB_TYPE_SOCKET || db->db_type == DKIMF_DB_TYPE_LUA) return -1; #ifdef USE_DB if (db->db_type != DKIMF_DB_TYPE_BDB && db->db_nrecs == 0) return 0; #endif /* USE_DB */ if ((db->db_type == DKIMF_DB_TYPE_FILE || db->db_type == DKIMF_DB_TYPE_CSL) && db->db_array != NULL) { *a = db->db_array; return db->db_nrecs; } found = FALSE; status = dkimf_db_get(db, "*", 0, NULL, 0, &found); if (status != 0) return -1; if (found && base != NULL) return dkimf_db_mkarray_base(db, a, base); switch (db->db_type) { case DKIMF_DB_TYPE_FILE: case DKIMF_DB_TYPE_CSL: { int c = 0; struct dkimf_db_list *cur; out = (char **) malloc(sizeof(char *) * (db->db_nrecs + 1)); if (out != NULL) { cur = db->db_handle; for (c = 0; c < db->db_nrecs; c++) { out[c] = cur->db_list_key; cur = cur->db_list_next; } out[c] = NULL; } db->db_array = out; *a = out; return c; } #ifdef USE_DB case DKIMF_DB_TYPE_BDB: #endif /* USE_DB */ #ifdef USE_ODBX case DKIMF_DB_TYPE_DSN: #endif /* USE_ODBX */ #if defined(USE_DB) || defined(USE_ODBX) { int c; int nr = 0; int na = 0; int status; size_t keylen; char keybuf[BUFRSZ + 1]; if (db->db_array != NULL) { for (c = 0; db->db_array[c] != NULL; c++) free(db->db_array[c]); free(db->db_array); db->db_array = NULL; } status = 0; while (status == 0) { memset(keybuf, '\0', sizeof keybuf); keylen = sizeof keybuf - 1; status = dkimf_db_walk(db, (nr == 0), keybuf, &keylen, NULL, 0); if (nr == 0) { out = (char **) malloc(sizeof(char *) * DEFARRAYSZ); if (out == NULL) return -1; out[0] = strdup(keybuf); if (out[0] == NULL) { free(out); return -1; } na = DEFARRAYSZ; nr = 1; out[nr] = NULL; } else { if (nr + 1 == na) { int newsz; char **newout; newsz = na * 2; newout = (char **) realloc(out, sizeof (char *) * newsz); if (newout == NULL) { for (c = 0; c < nr; c++) free(out[c]); free(out); return -1; } na = newsz; } out[nr] = strdup(keybuf); if (out[nr] == NULL) { for (c = 0; c < nr; c++) free(out[c]); free(out); return -1; } nr++; out[nr] = NULL; } } if (status == -1) { for (c = 0; c < nr; c++) free(out[c]); free(out); return -1; } db->db_array = out; db->db_iflags |= DKIMF_DB_IFLAG_FREEARRAY; *a = out; return nr; } #endif /* defined(USE_DB) || defined(USE_ODBX) */ default: return -1; } } /* ** DKIMF_DB_REWALK -- walk a regular expression DB looking for matches ** ** Parameters: ** db -- database of interest ** str -- string to match ** req -- list of data requests ** reqnum -- number of data requests ** ctx -- context pointer (updated) (may be NULL) ** ** Return value: ** -1 -- error ** 0 -- match found ** 1 -- no match found */ int dkimf_db_rewalk(DKIMF_DB db, char *str, DKIMF_DBDATA req, unsigned int reqnum, void **ctx) { int status; struct dkimf_db_relist *re; assert(db != NULL); assert(str != NULL); if (db->db_type != DKIMF_DB_TYPE_REFILE) return -1; if (ctx != NULL && *ctx != NULL) { re = (struct dkimf_db_relist *) *ctx; if (re->db_relist_next == NULL) return 1; else re = re->db_relist_next; } else { re = (struct dkimf_db_relist *) db->db_handle; } while (re != NULL) { status = regexec(&re->db_relist_re, str, 0, NULL, 0); if (status == 0) { if (ctx != NULL) *ctx = re; if (dkimf_db_datasplit(re->db_relist_data, strlen(re->db_relist_data), req, reqnum) != 0) { return -1; } else { return 0; } } else if (status != REG_NOMATCH) { return -1; } re = re->db_relist_next; } return 1; } /* ** DKIMF_DB_SET_LDAP_PARAM -- set an LDAP parameter ** ** Parameters: ** param -- parameter code to set ** str -- new string pointer value ** ** Return value: ** None. */ void dkimf_db_set_ldap_param(int param, char *str) { assert(param >= 0 && param <= DKIMF_LDAP_PARAM_MAX); dkimf_db_ldap_param[param] = str; } /* ** DKIMF_DB_CHOWN -- set ownership and permissions on a DB ** ** Parameters: ** db -- DKIMF_DB handle ** uid -- target uid ** ** Return value: ** 1 -- success ** 0 -- not a DB that can be chowned ** -1 -- fchown() failed */ int dkimf_db_chown(DKIMF_DB db, uid_t uid) { #ifdef USE_DB int fd = -1; int status = 0; DB *bdb; #endif /* USE_DB */ assert(db != NULL); assert(uid >= 0); if (dkimf_db_type(db) != DKIMF_DB_TYPE_BDB || (db->db_flags & DKIMF_DB_FLAG_READONLY) != 0 || (db->db_flags & DKIMF_DB_FLAG_NOFDLOCK) != 0) return 0; #ifdef USE_DB bdb = (DB *) db->db_handle; # if DB_VERSION_CHECK(2,0,0) status = bdb->fd(bdb, &fd); # else /* DB_VERSION_CHECK(2,0,0) */ fd = bdb->fd(bdb); # endif /* DB_VERSION_CHECK(2,0,0) */ if (status != 0 || fd == -1) return 0; if (fchown(fd, uid, -1) != 0) return -1; else return 1; #else /* USE_DB */ return 0; #endif /* USE_DB */ } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-db.h000066400000000000000000000057571337314105200226430ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. ** */ #ifndef _OPENDKIM_DB_H_ #define _OPENDKIM_DB_H_ /* system includes */ #include #include /* macros */ #define DKIMF_DB_FLAG_READONLY 0x0001 #define DKIMF_DB_FLAG_ICASE 0x0002 #define DKIMF_DB_FLAG_MATCHBOTH 0x0004 #define DKIMF_DB_FLAG_VALLIST 0x0008 #define DKIMF_DB_FLAG_USETLS 0x0010 #define DKIMF_DB_FLAG_MAKELOCK 0x0020 #define DKIMF_DB_FLAG_ASCIIONLY 0x0040 #define DKIMF_DB_FLAG_NOFDLOCK 0x0080 #define DKIMF_DB_FLAG_SOFTSTART 0x0100 #define DKIMF_DB_FLAG_NOCACHE 0x0200 #define DKIMF_DB_TYPE_UNKNOWN (-1) #define DKIMF_DB_TYPE_FILE 0 #define DKIMF_DB_TYPE_REFILE 1 #define DKIMF_DB_TYPE_CSL 2 #define DKIMF_DB_TYPE_BDB 3 #define DKIMF_DB_TYPE_DSN 4 #define DKIMF_DB_TYPE_LDAP 5 #define DKIMF_DB_TYPE_LUA 6 #define DKIMF_DB_TYPE_MEMCACHE 7 #define DKIMF_DB_TYPE_REPUTE 8 #define DKIMF_DB_TYPE_SOCKET 9 #define DKIMF_DB_TYPE_MDB 10 #define DKIMF_DB_TYPE_ERLANG 11 #define DKIMF_LDAP_PARAM_BINDUSER 0 #define DKIMF_LDAP_PARAM_BINDPW 1 #define DKIMF_LDAP_PARAM_AUTHMECH 2 #define DKIMF_LDAP_PARAM_USETLS 3 #define DKIMF_LDAP_PARAM_AUTHREALM 4 #define DKIMF_LDAP_PARAM_AUTHUSER 5 #define DKIMF_LDAP_PARAM_AUTHNAME 6 #define DKIMF_LDAP_PARAM_TIMEOUT 7 #define DKIMF_LDAP_PARAM_KA_IDLE 8 #define DKIMF_LDAP_PARAM_KA_PROBES 9 #define DKIMF_LDAP_PARAM_KA_INTERVAL 10 #define DKIMF_LDAP_PARAM_MAX 10 #ifdef __STDC__ # ifndef __P # define __P(x) x # endif /* ! __P */ #else /* __STDC__ */ # ifndef __P # define __P(x) () # endif /* ! __P */ #endif /* __STDC__ */ /* types */ struct dkimf_db; typedef struct dkimf_db * DKIMF_DB; struct dkimf_db_data { unsigned int dbdata_flags; char * dbdata_buffer; size_t dbdata_buflen; }; typedef struct dkimf_db_data * DKIMF_DBDATA; #define DKIMF_DB_DATA_BINARY 0x01 /* data is binary */ #define DKIMF_DB_DATA_OPTIONAL 0x02 /* data is optional */ /* prototypes */ extern int dkimf_db_chown __P((DKIMF_DB, uid_t uid)); extern int dkimf_db_close __P((DKIMF_DB)); extern int dkimf_db_delete __P((DKIMF_DB, void *, size_t)); extern void dkimf_db_flags __P((unsigned int)); extern int dkimf_db_get __P((DKIMF_DB, void *, size_t, DKIMF_DBDATA, unsigned int, _Bool *)); extern int dkimf_db_mkarray __P((DKIMF_DB, char ***, const char **)); extern int dkimf_db_open __P((DKIMF_DB *, char *, u_int flags, pthread_mutex_t *, char **)); extern int dkimf_db_put __P((DKIMF_DB, void *, size_t, void *, size_t)); extern int dkimf_db_rewalk __P((DKIMF_DB, char *, DKIMF_DBDATA, unsigned int, void **)); extern void dkimf_db_set_ldap_param __P((int, char *)); extern int dkimf_db_strerror __P((DKIMF_DB, char *, size_t)); extern int dkimf_db_type __P((DKIMF_DB)); extern int dkimf_db_walk __P((DKIMF_DB, _Bool, void *, size_t *, DKIMF_DBDATA, unsigned int)); #endif /* _OPENDKIM_DB_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-dns.c000066400000000000000000000521361337314105200230260ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include /* libopendkim includes */ #include #ifdef USE_UNBOUND /* libunbound includes */ # include #endif /* USE_UNBOUND */ #ifdef _FFR_RBL /* librbl includes */ # include #endif /* _FFR_RBL */ #ifdef _FFR_VBR /* libvbr includes */ # include #endif /* _FFR_VBR */ /* opendkim includes */ #include "opendkim-dns.h" #include "opendkim-db.h" #include "util.h" /* macros */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ #define BUFRSZ 1024 #define MAXPACKET 8192 /* struct dkimf_fquery -- a file-based DNS query */ struct dkimf_fquery { unsigned char * fq_rbuf; size_t fq_rbuflen; size_t fq_qlen; unsigned char fq_qbuf[MAXPACKET]; }; #ifdef USE_UNBOUND /* struct dkimf_unbound -- unbound context */ struct dkimf_unbound { _Bool ub_poller; struct ub_ctx * ub_ub; pthread_mutex_t ub_lock; pthread_mutex_t ub_config_lock; pthread_cond_t ub_ready; }; /* struct dkimf_unbound_cb_data -- libunbound callback data */ struct dkimf_unbound_cb_data { int ubd_done; int ubd_rcode; int ubd_id; int ubd_type; int ubd_result; DKIM_STAT ubd_stat; size_t ubd_buflen; u_char * ubd_buf; const char * ubd_strerror; }; #endif /* USE_UNBOUND */ /* ** DKIMF_DNS_TRUSTANCHOR -- advise the DKIM library of new trust anchor data ** ** Parameters: ** lib -- DKIM library handle ** trust -- trust anchor data ** ** Return value: ** DKIM_DNS_SUCCESS or DKIM_DNS_ERROR */ int dkimf_dns_trustanchor(DKIM_LIB *lib, const char *trust) { assert(lib != NULL); assert(trust != NULL); return dkim_dns_trustanchor(lib, trust); } /* ** DKIMF_DNS_SETNAMESERVERS -- advise the DKIM library of new nameservers ** ** Parameters: ** lib -- DKIM library handle ** nslist -- nameserver list ** ** Return value: ** DKIM_DNS_SUCCESS or DKIM_DNS_ERROR */ int dkimf_dns_setnameservers(DKIM_LIB *lib, const char *nslist) { assert(lib != NULL); assert(nslist != NULL); return dkim_dns_nslist(lib, nslist); } /* ** DKIMF_DNS_CONFIG -- pass arbitrary configuration to the resolver ** ** Parameters: ** lib -- DKIM library handle ** config -- resolver configuration data ** ** Return value: ** DKIM_DNS_SUCCESS or DKIM_DNS_ERROR */ int dkimf_dns_config(DKIM_LIB *lib, const char *config) { assert(lib != NULL); assert(config != NULL); return dkim_dns_config(lib, config); } #ifdef USE_UNBOUND /* ** DKIMF_UNBOUND_CB -- callback to handle result of DNS query ** ** Parameters: ** mydata -- structure to return data to DKIM_GET_KEY_DNS ** err -- error code from unbound resolver ** result -- result of DNS query ** ** Return value: ** None. */ static void dkimf_unbound_cb(void *mydata, int err, struct ub_result *result) { struct dkimf_unbound_cb_data *ubdata; ubdata = (struct dkimf_unbound_cb_data *) mydata; if (err != 0) { ubdata->ubd_done = TRUE; ubdata->ubd_stat = DKIM_STAT_INTERNAL; ubdata->ubd_strerror = ub_strerror(err); return; } ubdata->ubd_done = FALSE; ubdata->ubd_stat = DKIM_STAT_NOKEY; ubdata->ubd_rcode = result->rcode; memcpy(ubdata->ubd_buf, result->answer_packet, MIN(ubdata->ubd_buflen, result->answer_len)); ubdata->ubd_buflen = result->answer_len; /* ** Check whether reply is either secure or insecure. If bogus, ** treat as if no key exists. */ if (result->secure) { ubdata->ubd_result = DKIM_DNSSEC_SECURE; } else if (result->bogus) { /* result was bogus */ ubdata->ubd_result = DKIM_DNSSEC_BOGUS; return; } else { ubdata->ubd_result = DKIM_DNSSEC_INSECURE; } if (result->havedata && !result->nxdomain && result->rcode == NOERROR) ubdata->ubd_stat = DKIM_STAT_OK; ub_resolve_free(result); ubdata->ubd_done = TRUE; } /* ** DKIMF_UNBOUND_WAIT -- wait for a reply from libunbound ** ** Parameters: ** ub -- unbound handle ** ubdata -- pointer to a struct dkimf_unbound_cb_data ** to -- timeout (or NULL) ** ** Return value: ** 1 -- success ** 0 -- timeout ** -1 -- error */ static int dkimf_unbound_wait(struct dkimf_unbound *ub, struct dkimf_unbound_cb_data *ubdata, struct timeval *to) { struct timespec timeout; struct timeval now; assert(ub != NULL); assert(ubdata != NULL); if (to != NULL) { (void) gettimeofday(&now, NULL); timeout.tv_sec = now.tv_sec + to->tv_sec; timeout.tv_nsec = now.tv_usec * 1000; timeout.tv_nsec += (1000 * to->tv_usec); if (timeout.tv_nsec > 1000000000) { timeout.tv_sec += (timeout.tv_nsec / 1000000000); timeout.tv_nsec = timeout.tv_nsec % 1000000000; } } pthread_mutex_lock(&ub->ub_lock); for (;;) { /* ** Wait for a signal unless/until: ** a) our request is done ** b) there's nobody polling libunbound for results ** c) we don't want to wait anymore (timeout) */ if (to != NULL) { while (!ubdata->ubd_done && ub->ub_poller && !dkimf_timespec_past(&timeout)) { (void) pthread_cond_timedwait(&ub->ub_ready, &ub->ub_lock, &timeout); } } else { while (!ubdata->ubd_done && ub->ub_poller) { (void) pthread_cond_wait(&ub->ub_ready, &ub->ub_lock); } } if (ubdata->ubd_done) { /* our request completed */ pthread_mutex_unlock(&ub->ub_lock); return 1; } else if (to != NULL && dkimf_timespec_past(&timeout)) { /* our request timed out */ pthread_mutex_unlock(&ub->ub_lock); return 0; } else { int status; /* nobody's waiting for results, so we will */ ub->ub_poller = TRUE; pthread_mutex_unlock(&ub->ub_lock); /* wait for I/O to be available */ status = dkimf_wait_fd(ub_fd(ub->ub_ub), to == NULL ? NULL : &timeout); if (status == 0) { /* no answer in time */ pthread_mutex_lock(&ub->ub_lock); ub->ub_poller = FALSE; pthread_cond_signal(&ub->ub_ready); pthread_mutex_unlock(&ub->ub_lock); return 0; } assert(status == 1); /* process anything pending */ status = ub_process(ub->ub_ub); if (status != 0) { /* error during processing */ pthread_mutex_lock(&ub->ub_lock); ub->ub_poller = FALSE; pthread_cond_signal(&ub->ub_ready); pthread_mutex_unlock(&ub->ub_lock); return -1; } /* recover the lock so the loop can restart */ pthread_mutex_lock(&ub->ub_lock); /* tell everyone to check for results */ pthread_cond_broadcast(&ub->ub_ready); /* clear the "someone is polling" flag */ ub->ub_poller = FALSE; } } } /* ** DKIMF_UNBOUND_QUEUE -- queue a request for processing by libunbound ** ** Parameters: ** ub -- unbound context ** name -- name to query ** type -- record type to request ** buf -- where to write the result ** buflen -- bytes available at "buf" ** cbdata -- callback data structure to use ** ** Return value: ** 0 -- success ** -1 -- error */ static int dkimf_unbound_queue(struct dkimf_unbound *ub, char *name, int type, u_char *buf, size_t buflen, struct dkimf_unbound_cb_data *cbdata) { int status; assert(ub != NULL); assert(name != NULL); assert(buf != NULL); assert(buflen > 0); assert(cbdata != NULL); cbdata->ubd_done = FALSE; cbdata->ubd_buf = buf; cbdata->ubd_buflen = buflen; cbdata->ubd_stat = DKIM_STAT_OK; cbdata->ubd_result = DKIM_DNSSEC_UNKNOWN; cbdata->ubd_rcode = NOERROR; cbdata->ubd_type = type; status = ub_resolve_async(ub->ub_ub, name, type, C_IN, (void *) cbdata, dkimf_unbound_cb, &cbdata->ubd_id); if (status != 0) return -1; return 0; } /* ** DKIMF_UB_TRUSTANCHOR -- add a trust anchor file to a libunbound context ** ** Parameters: ** srv -- service handle ** file -- path to add ** ** Return value: ** 0 -- success ** -1 -- error */ int dkimf_ub_trustanchor(void *srv, const char *file) { int status; struct dkimf_unbound *ub; assert(srv != NULL); assert(file != NULL); ub = srv; status = ub_ctx_add_ta_file(ub->ub_ub, (char *) file); return (status == 0 ? 0 : -1); } /* ** DKIMF_UB_CONFIG -- add a configuration file to a libunbound context ** ** Parameters: ** srv -- void service handle ** file -- path to add ** ** Return value: ** 0 -- success ** -1 -- error */ int dkimf_ub_config(void *srv, const char *file) { int status; struct dkimf_unbound *ub; assert(srv != NULL); assert(file != NULL); ub = srv; pthread_mutex_lock(&ub->ub_config_lock); status = ub_ctx_config(ub->ub_ub, (char *) file); pthread_mutex_unlock(&ub->ub_config_lock); return (status == 0 ? 0 : -1); } /* ** DKIMF_UB_CANCEL -- function passed to libopendkim to handle cancel requests ** ** Parameters: ** srv -- service handle ** q -- query handle ** ** Return value: ** A DKIM_DNS_* constant. */ static int dkimf_ub_cancel(void *srv, void *q) { struct dkimf_unbound *ub; struct dkimf_unbound_cb_data *ubdata; assert(srv != NULL); assert(q != NULL); ub = (struct dkimf_unbound *) srv; ubdata = (struct dkimf_unbound_cb_data *) q; (void) ub_cancel(ub->ub_ub, ubdata->ubd_id); free(q); return DKIM_DNS_SUCCESS; } /* ** DKIMF_UB_QUERY -- function passed to libopendkim to handle new requests ** ** Parameters: ** srv -- service handle ** ** Return value: ** A DKIM_DNS_* constant. */ static int dkimf_ub_query(void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh) { int status; struct dkimf_unbound *ub; struct dkimf_unbound_cb_data *ubdata; assert(srv != NULL); assert(query != NULL); assert(buf != NULL); assert(qh != NULL); ub = (struct dkimf_unbound *) srv; ubdata = (struct dkimf_unbound_cb_data *) malloc(sizeof *ubdata); if (ubdata == NULL) return DKIM_DNS_ERROR; memset(ubdata, '\0', sizeof *ubdata); status = dkimf_unbound_queue(ub, (char *) query, type, buf, buflen, ubdata); if (status != 0) { free(ubdata); return DKIM_DNS_ERROR; } *qh = ubdata; return DKIM_DNS_SUCCESS; } /* ** DKIMF_UB_WAITREPLY -- function passed to libopendkim to handle ** wait requests ** ** Parameters: ** srv -- service handle ** q -- query handle ** to -- wait timeout ** bytes -- bytes (returned) ** error -- error code (returned) ** dnssec -- DNSSEC status (returned) ** ** Return value: ** A DKIM_DNS_* constant. */ static int dkimf_ub_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec) { int status; struct dkimf_unbound *ub; struct dkimf_unbound_cb_data *ubdata; assert(srv != NULL); assert(qh != NULL); ub = (struct dkimf_unbound *) srv; ubdata = (struct dkimf_unbound_cb_data *) qh; status = dkimf_unbound_wait(ub, ubdata, to); if (status == 1 || status == -1) { if (dnssec != NULL) *dnssec = ubdata->ubd_result; if (bytes != NULL) *bytes = ubdata->ubd_buflen; if (error != NULL && status == -1) *error = status; /* XXX -- improve this */ } if (status == 0) return DKIM_DNS_EXPIRED; else if (status == 1) return DKIM_DNS_SUCCESS; else return DKIM_DNS_ERROR; } /* =========================== PUBLIC FUNCTIONS =========================== */ /* ** DKIMF_UB_INIT -- set up a libunbound context and other data ** ** Parameters: ** ub -- unbound context (returned) ** ** Return value: ** DKIM_DNS_SUCCESS -- success ** DKIM_DNS_ERROR -- failure */ int dkimf_ub_init(void **ub) { struct dkimf_unbound *out; assert(ub != NULL); out = (struct dkimf_unbound *) malloc(sizeof *out); if (out == NULL) return DKIM_DNS_ERROR; out->ub_ub = ub_ctx_create(); if (out->ub_ub == NULL) { free(out); return DKIM_DNS_ERROR; } /* suppress debug output */ (void) ub_ctx_debugout(out->ub_ub, NULL); /* set for asynchronous operation */ ub_ctx_async(out->ub_ub, TRUE); out->ub_poller = FALSE; pthread_mutex_init(&out->ub_lock, NULL); pthread_mutex_init(&out->ub_config_lock, NULL); pthread_cond_init(&out->ub_ready, NULL); *ub = out; return DKIM_DNS_SUCCESS; } /* ** DKIMF_UB_CLOSE -- shut down a libunbound context ** ** Parameters: ** ub -- unbound context ** ** Return value: ** 0 -- success ** -1 -- failure */ void dkimf_ub_close(void *srv) { struct dkimf_unbound *ub; assert(srv != NULL); ub = srv; ub_ctx_delete(ub->ub_ub); pthread_mutex_destroy(&ub->ub_lock); pthread_mutex_destroy(&ub->ub_config_lock); pthread_cond_destroy(&ub->ub_ready); free(srv); } /* ** DKIMF_UB_NSLIST -- set nameserver list ** ** Parameters: ** srv -- unbound service handle (as a void *) ** nslist -- nameserver list ** ** Return value: ** DKIM_DNS_SUCCESS or DKIM_DNS_ERROR */ int dkimf_ub_nslist(void *srv, const char *nslist) { char *cp; char *p; char *last = NULL; struct dkimf_unbound *ub; assert(srv != NULL); assert(nslist != NULL); ub = srv; cp = strdup(nslist); if (cp == NULL) return DKIM_DNS_ERROR; for (p = strtok_r(cp, ",", &last); p != NULL; p = strtok_r(NULL, ",", &last)) { if (ub_ctx_set_fwd(ub->ub_ub, p) != 0) { free(cp); return DKIM_DNS_ERROR; } } free(cp); return DKIM_DNS_SUCCESS; } # ifdef _FFR_RBL /* ** DKIMF_RBL_UNBOUND_SETUP -- connect libunbound to librbl ** ** Parameters: ** rbl -- librbl handle ** ub -- dkimf_unbound handle to use ** ** Return value: ** 0 on success, -1 on failure */ int dkimf_rbl_unbound_setup(RBL *rbl) { assert(rbl != NULL); (void) rbl_dns_set_query_start(rbl, dkimf_ub_query); (void) rbl_dns_set_query_cancel(rbl, dkimf_ub_cancel); (void) rbl_dns_set_query_waitreply(rbl, dkimf_ub_waitreply); (void) rbl_dns_set_init(rbl, dkimf_ub_init); (void) rbl_dns_set_close(rbl, dkimf_ub_close); (void) rbl_dns_set_nslist(rbl, dkimf_ub_nslist); (void) rbl_dns_set_config(rbl, dkimf_ub_config); (void) rbl_dns_set_trustanchor(rbl, dkimf_ub_trustanchor); return 0; } # endif /* _FFR_RBL */ /* ** DKIMF_UNBOUND_SETUP -- connect libunbound to libopendkim ** ** Parameters: ** lib -- libopendkim handle ** ub -- dkimf_unbound handle to use ** ** Return value: ** 0 on success, -1 on failure */ int dkimf_unbound_setup(DKIM_LIB *lib) { assert(lib != NULL); (void) dkim_dns_set_query_start(lib, dkimf_ub_query); (void) dkim_dns_set_query_cancel(lib, dkimf_ub_cancel); (void) dkim_dns_set_query_waitreply(lib, dkimf_ub_waitreply); (void) dkim_dns_set_init(lib, dkimf_ub_init); (void) dkim_dns_set_close(lib, dkimf_ub_close); (void) dkim_dns_set_nslist(lib, dkimf_ub_nslist); (void) dkim_dns_set_config(lib, dkimf_ub_config); (void) dkim_dns_set_trustanchor(lib, dkimf_ub_trustanchor); return 0; } #endif /* USE_UNBOUND */ /* ** DKIMF_FILEDNS_QUERY -- function passed to libopendkim to handle new ** requests ** ** Parameters: ** srv -- service handle ** ** Return value: ** A DKIM_DNS_* constant. */ static int dkimf_filedns_query(void *srv, int type, unsigned char *query, unsigned char *buf, size_t buflen, void **qh) { struct dkimf_fquery *fq; size_t qlen; assert(srv != NULL); assert(query != NULL); assert(buf != NULL); assert(qh != NULL); if (type != T_TXT) return DKIM_DNS_SUCCESS; fq = malloc(sizeof *fq); if (fq == NULL) return DKIM_DNS_ERROR; fq->fq_rbuf = buf; fq->fq_rbuflen = buflen; qlen = res_mkquery(QUERY, query, C_IN, type, NULL, 0, NULL, fq->fq_qbuf, sizeof fq->fq_qbuf); if (qlen == (size_t) -1) { free(fq); return DKIM_DNS_ERROR; } fq->fq_qlen = qlen; *qh = fq; return DKIM_DNS_SUCCESS; } /* ** DKIMF_FILEDNS_CANCEL -- function passed to libopendkim to handle cancel ** requests ** ** Parameters: ** srv -- service handle ** q -- query handle ** ** Return value: ** A DKIM_DNS_* constant. */ static int dkimf_filedns_cancel(void *srv, void *q) { struct dkimf_fquery *fq; assert(srv != NULL); assert(q != NULL); fq = q; free(fq); return DKIM_DNS_SUCCESS; } /* ** DKIMF_FILEDNS_WAITREPLY -- function passed to libopendkim to handle ** wait requests ** ** Parameters: ** srv -- service handle ** q -- query handle ** to -- wait timeout ** bytes -- bytes (returned) ** error -- error code (returned) ** dnssec -- DNSSEC status (returned) ** ** Return value: ** A DKIM_DNS_* constant. */ static int dkimf_filedns_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, int *error, int *dnssec) { _Bool exists = FALSE; int n; int status; int qdcount; char *cp; char *eom; char *qstart; struct dkimf_fquery *fq; char qname[BUFRSZ + 1]; char buf[BUFRSZ + 1]; HEADER hdr; struct dkimf_db_data dbd; assert(srv != NULL); assert(qh != NULL); fq = (struct dkimf_fquery *) qh; /* recover the query */ qstart = fq->fq_rbuf; cp = fq->fq_qbuf; eom = cp + sizeof fq->fq_qbuf; memcpy(&hdr, cp, sizeof hdr); cp += HFIXEDSZ; /* skip over the name at the front of the answer */ memset(qname, '\0', sizeof qname); for (qdcount = ntohs((unsigned short) hdr.qdcount); qdcount > 0; qdcount--) { /* copy it first */ (void) dn_expand((unsigned char *) fq->fq_qbuf, eom, cp, (char *) qname, sizeof qname); if ((n = dn_skipname(cp, eom)) < 0) return DKIM_DNS_ERROR;; cp += n; /* extract the type and class */ if (cp + INT16SZ + INT16SZ > eom) return DKIM_DNS_ERROR; ; cp += (INT16SZ + INT16SZ); } /* search the DB */ dbd.dbdata_buffer = buf; dbd.dbdata_buflen = sizeof buf; dbd.dbdata_flags = 0; memset(buf, '\0', sizeof buf); /* see if it's in the DB */ status = dkimf_db_get((DKIMF_DB) srv, qname, strlen(qname), &dbd, 1, &exists); if (status != 0) return DKIM_DNS_ERROR; /* prepare a reply header */ hdr.qr = 1; if (!exists) { /* not found; set up an NXDOMAIN reply */ hdr.rcode = NXDOMAIN; hdr.ancount = htons(0); memcpy(fq->fq_qbuf, &hdr, sizeof hdr); *bytes = fq->fq_qlen; } else { /* found, construct the reply */ int elen; int slen; int olen; char *q; unsigned char *len; unsigned char *dnptrs[3]; unsigned char **lastdnptr; HEADER newhdr; lastdnptr = &dnptrs[2]; memset(&newhdr, '\0', sizeof newhdr); memset(&dnptrs, '\0', sizeof dnptrs); newhdr.qdcount = htons(1); newhdr.ancount = htons(1); newhdr.rcode = NOERROR; newhdr.opcode = hdr.opcode; newhdr.qr = 1; newhdr.id = hdr.id; dnptrs[0] = fq->fq_qbuf; /* copy out the new header */ memcpy(fq->fq_rbuf, &newhdr, sizeof newhdr); cp = fq->fq_rbuf + HFIXEDSZ; eom = fq->fq_rbuf + fq->fq_rbuflen; /* question section */ elen = dn_comp(qname, cp, eom - cp, dnptrs, lastdnptr); if (elen == -1) return DKIM_DNS_ERROR; cp += elen; PUTSHORT(T_TXT, cp); PUTSHORT(C_IN, cp); /* answer section */ elen = dn_comp(qname, cp, eom - cp, dnptrs, lastdnptr); if (elen == -1) return DKIM_DNS_ERROR; cp += elen; PUTSHORT(T_TXT, cp); PUTSHORT(C_IN, cp); PUTLONG(0L, cp); len = cp; cp += INT16SZ; slen = dbd.dbdata_buflen; olen = 0; q = buf; while (slen > 0) { elen = MIN(slen, 255); *cp = (char) elen; cp++; olen++; memcpy(cp, q, elen); q += elen; cp += elen; olen += elen; slen -= elen; } eom = cp; cp = len; PUTSHORT(olen, cp); *bytes = eom - qstart; } if (dnssec != NULL) *dnssec = DKIM_DNSSEC_UNKNOWN; return DKIM_DNS_SUCCESS; } /* ** DKIMF_FILEDNS_SETUP -- connect a file DNS to libopendkim ** ** Parameters: ** lib -- libopendkim handle ** db -- data set from which to read ** ** Return value: ** 0 on success, -1 on failure */ int dkimf_filedns_setup(DKIM_LIB *lib, DKIMF_DB db) { assert(lib != NULL); assert(db != NULL); (void) dkim_dns_set_query_service(lib, db); (void) dkim_dns_set_query_start(lib, dkimf_filedns_query); (void) dkim_dns_set_query_cancel(lib, dkimf_filedns_cancel); (void) dkim_dns_set_query_waitreply(lib, dkimf_filedns_waitreply); (void) dkim_dns_set_init(lib, NULL); (void) dkim_dns_set_close(lib, NULL); (void) dkim_dns_set_nslist(lib, NULL); (void) dkim_dns_set_config(lib, NULL); (void) dkim_dns_set_trustanchor(lib, NULL); return 0; } #ifdef _FFR_VBR # ifdef USE_UNBOUND /* ** DKIMF_VBR_UNBOUND_SETUP -- connect libunbound to libvbr ** ** Parameters: ** vbr -- libvbr handle ** ub -- dkimf_unbound handle to use ** ** Return value: ** 0 on success, -1 on failure */ int dkimf_vbr_unbound_setup(VBR *vbr) { assert(vbr != NULL); (void) vbr_dns_set_query_start(vbr, dkimf_ub_query); (void) vbr_dns_set_query_cancel(vbr, dkimf_ub_cancel); (void) vbr_dns_set_query_waitreply(vbr, dkimf_ub_waitreply); (void) vbr_dns_set_init(vbr, dkimf_ub_init); (void) vbr_dns_set_close(vbr, dkimf_ub_close); (void) vbr_dns_set_nslist(vbr, dkimf_ub_nslist); (void) vbr_dns_set_config(vbr, dkimf_ub_config); (void) vbr_dns_set_trustanchor(vbr, dkimf_ub_trustanchor); return 0; } # endif /* USE_UNBOUND */ #endif /* _FFR_VBR */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-dns.h000066400000000000000000000023231337314105200230240ustar00rootroot00000000000000/* ** Copyright (c) 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. */ #ifndef _OPENDKIM_DNS_H_ #define _OPENDKIM_DNS_H_ /* system includes */ #include /* libopendkim includes */ #include /* opendkim includes */ #include "opendkim-db.h" #ifdef _FFR_RBL /* librbl includes */ # include #endif /* _FFR_RBL */ #ifdef _FFR_VBR /* libvbr includes */ # include #endif /* _FFR_VBR */ struct dkimf_filedns; #ifdef USE_UNBOUND /* libunbound includes */ # include /* prototypes */ extern int dkimf_unbound_setup __P((DKIM_LIB *)); # ifdef _FFR_RBL extern int dkimf_rbl_unbound_setup __P((RBL *)); # endif /* _FFR_RBL */ # ifdef _FFR_VBR extern int dkimf_vbr_unbound_setup __P((VBR *)); # endif /* _FFR_VBR */ #endif /* USE_UNBOUND */ extern int dkimf_filedns_free __P((struct dkimf_filedns *)); extern int dkimf_filedns_setup __P((DKIM_LIB *, DKIMF_DB)); extern int dkimf_dns_config __P((DKIM_LIB *, const char *)); extern int dkimf_dns_setnameservers __P((DKIM_LIB *, const char *)); extern int dkimf_dns_trustanchor __P((DKIM_LIB *, const char *)); #endif /* _OPENDKIM_DNS_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-genkey.8.in000066400000000000000000000057651337314105200240640ustar00rootroot00000000000000.TH opendkim-genkey 8 "The Trusted Domain Project" .SH NAME .B opendkim-genkey \- DKIM filter key generation tool .SH SYNOPSIS .B opendkim-genkey [options] .SH DESCRIPTION .B opendkim-genkey generates (1) a private key for signing messages using .I opendkim(8) and (2) a DNS TXT record suitable for inclusion in a zone file which publishes the matching public key for use by remote DKIM verifiers. The filenames of these are based on the selector (see below); the private key will have a suffix of ".private" and the TXT record will have a suffix of ".txt". Both long and short names are supported for most options. .SH OPTIONS .TP .I \-a (\-\-append-domain) Appends the domain name (see \-d below) to the label in the generated TXT record, followed by a trailing period. By default it is assumed the domain name is implicit from the context of the zone file, and is therefore not included in the output. .TP .I \-b bits (\-\-bits=n) Specifies the size of the key, in .I bits, to be generated. The default is 1024 which is the value recommended by the DKIM specification. .TP .I \-d domain (\-\-domain=string) Names the .I domain which will use this key for signing. Currently only used in a comment in the TXT record file. The default is "@DOMAIN@". .TP .I \-D directory (\-\-directory=path) Instructs the tool to change to the named .I directory prior to creating files. By default the current directory is used. .TP .I \-h algorithms (\-\-hash-algorithms=name[:name[...]]) Specifies a list of hash .I algorithms which can be used with this key. By default all hash algorithms are allowed. .TP .I \-\-help Print a help message and exit. .TP .I \-n note (\-\-note=string) Includes arbitrary .I note text in the key record. By default, no such text is included. .TP .I \-r (\-\-restricted) Restricts the key for use in e-mail signing only. The default is to allow the key to be used for any service. .TP .I \-s selector (\-\-selector=name) Specifies the .I selector, or name, of the key pair generated. The default is "default". .TP .I \-S (\-\-[no]subdomains) Disallows subdomain signing by this key. By default the key record will be generated such that verifiers are told subdomain signing is permitted. Note that for backward compatibility reasons, .I \-S means the same as .I \-\-nosubdomains. .TP .I \-t (\-\-[no]testmode) Indicates the generated key record should be tagged such that verifiers are aware DKIM is in test at the signing domain. .TP .I -v (\-\-verbose) Increase verbose output. .TP .I -V (\-\-version) Print version number and exit. .SH NOTES Requires that the .I openssl(8) binary be installed and in the executing shell's search path. .SH VERSION This man page covers the version of .I opendkim-genkey that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. All rights reserved. Copyright (c) 2009, 2011-2013, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I openssl(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-genkey.in000066400000000000000000000144521337314105200237070ustar00rootroot00000000000000#!/usr/bin/perl ## ## Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. ## All rights reserved. ## ## Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. ## ## opendkim-genkey -- generate a key and/or TXT record for DKIM service ## ## The output of this script includes two files based on the ## selector name: ## ## .private PEM-formatted private key, for use by ## opendkim when signing messages ## ## .txt A DNS TXT record suitable for insertion ## into or inclusion by a DNS zone file ## in order to publish the public key ## for retrieval by verifiers use strict; use warnings; use File::Basename; use Getopt::Long; ## ## Set up defaults ## my $bits = 1024; my $domain = "@DOMAIN@"; my $version = "@DOMAIN@"; my $outdir = "."; my $nosubdomains = 0; my $subdomains = 1; my $hashalgs; my $note; my $flags = ""; my $selector = "default"; my $restricted = 0; my $testmode = 0; my $verbose = 0; my $append = 0; my $showversion = 0; my $keyin; my $status; my $txtout; my $keydata; my $helponly; my $hashout; my $noteout; my $comment; my $len; my $cur; my $domstr; my $progname = basename($0); ## ## Usage message ## sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--append-domain include domain name in zone file stub\n"; print STDERR "\t--bits=n use n bits to generate the key\n"; print STDERR "\t--directory=path leave output in the named directory\n"; print STDERR "\t--domain=name generate data for the named domain [$domain]\n"; print STDERR "\t--hash-algorithms=list limit to use of the named algorithm(s)\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--note=string include specified note in zone data\n"; print STDERR "\t--restrict restrict key to email use only\n"; print STDERR "\t--selector=name selector name [$selector]\n"; print STDERR "\t--subdomains allow signing of subdomains\n"; print STDERR "\t--testmode indicate key is in test mode\n"; print STDERR "\t--verbose increased output\n"; print STDERR "\t--version print version and exit\n"; } ## ## Argument processing ## # parse command line arguments Getopt::Long::Configure("bundling"); my $opt_retval = &Getopt::Long::GetOptions('a|append-domain!' => \$append, 'b|bits=i' => \$bits, 'D|directory=s' => \$outdir, 'd|domain=s' => \$domain, 'h|hash-algorithms=s' => \$hashalgs, 'help!' => \$helponly, 'n|note=s' => \$note, 'r|restrict!' => \$restricted, 's|selector=s' => \$selector, 'S!' => \$nosubdomains, 'subdomains!' => \$subdomains, 't|testmode!' => \$testmode, 'v|verbose+' => \$verbose, 'V|version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v@VERSION@\n"; exit 0; } ## do this securely and in the right place chdir($outdir) or die "$progname: $outdir: chdir(): $!";; umask(077); ## generate a private key if ($verbose >= 1) { print STDERR "$progname: generating private key\n"; } if ($bits < 1024) { print STDERR "$progname: WARNING: RFC6376 advises minimum 1024-bit keys\n"; } $status = system("openssl genrsa -out " . $selector . ".private " . $bits . " > /dev/null 2>&1"); if ($status != 0) { if ($? & 127) { print STDERR "$progname: openssl died with signal %d\n", ($? & 127); exit(1); } else { print STDERR "$progname: openssl exited with status %d\n", ($? >> 8); exit(1); } } if ($verbose) { print STDERR "$progname: private key written to " . $selector . ".private\n"; } ## generate a public key based on the private key if ($verbose) { print STDERR "$progname: extracting public key\n"; } $status = system("openssl rsa -in " . $selector . ".private -pubout -out " . $selector . ".public -outform PEM > /dev/null 2>&1"); if ($status != 0) { if ($? & 127) { print STDERR "$progname: openssl died with signal %d\n", ($? & 127); exit(1); } else { print STDERR "$progname: openssl exited with status %d\n", ($? >> 8); exit(1); } } if (!open($keyin, "<", $selector . ".public")) { print STDERR "$progname: unable to read from " . $selector . ".public: $!\n"; exit(1); } while (<$keyin>) { chomp; if ($_ =~ /^-/) { next; } $keydata .= $_; } close($keyin); ## output the record if ($testmode) { $flags = "t=y;"; } if ($nosubdomains) { $subdomains = 0; } if (!$subdomains) { if ($flags eq "t=y;") { $flags = "t=y:s;"; } else { $flags = "t=s;"; } } if ($restricted) { if ($flags ne "") { $flags .= " "; } $flags .= "s=email;"; } if ($flags ne "") { $flags .= " "; } $hashout = ""; if (defined($hashalgs)) { $hashout = " h=$hashalgs;"; } $noteout = ""; if (defined($note)) { $noteout = " n=\\\"$note\\\";"; } $domstr = ""; if ($append) { $domstr = "." . $domain . "."; } if ($domain ne "") { $comment = " ; ----- DKIM key $selector for $domain" } else { $comment = ""; } if (!open($txtout, ">", $selector . ".txt")) { print STDERR "$progname: unable to write from " . $selector . ".txt: $!\n"; exit(1); } print $txtout $selector . "._domainkey" . ${domstr} . "\tIN\tTXT\t( \"v=DKIM1;" . $noteout . $hashout . " k=rsa; " . $flags . "\"\n\t \"p="; $len = length($keydata); $cur = 0; while ($len > 0) { if ($len < 250) { print $txtout substr($keydata, $cur); $len = 0; } else { print $txtout substr($keydata, $cur, 250); print $txtout "\"\n\t \""; $cur += 250; $len -= 250; } } print $txtout "\" ) " . $comment . "\n"; close($txtout); if ($verbose) { print STDERR "$progname: DNS TXT record written to " . $selector . ".txt\n"; } ## all done! unlink($selector . ".public"); exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-genzone.8.in000066400000000000000000000067001337314105200242350ustar00rootroot00000000000000.TH opendkim-genzone 8 "The Trusted Domain Project" .SH NAME .B opendkim-genzone \- DKIM public key zone file generation tool .SH SYNOPSIS .B opendkim-genzone [\-C address] [\-d domain] [\-D] [\-E secs] [\-F] [\-N ns[,...]] [\-o file] [\-r secs] [\-R secs] [\-s] [\-S] [\-t secs] [\-T secs] [\-u] [\-v] [\-x conffile] [dataset] .SH DESCRIPTION .B opendkim-genzone generates a file suitable for use with .I named(8) to publish a set of public keys. The .I dataset parameter should specify a set of data as described in the .I opendkim(8) man page. It can currently refer to flat files, Sleepycat databases, comma-separated lists, LDAP directories or SQL databases. The .I dataset may be omitted if a configuration file (via the .I \-x command line flag) is specified referring to a configuration file that sets a .I KeyTable parameter, in which case that value will be used. The database contents should be formatted as described for the .I KeyTable parameter, described in the .I opendkim.conf(5) man page. .SH OPTIONS .TP .I \-C contact Uses .I contact as the contact information to be used when an SOA record is generated (see .I \-S below). If not specified, the userid of the executing user and the local hostname will be used; if the executing user can't be determined, "hostmaster" will be used. .TP .I \-d domain Restricts output to those records for which the domain field is the specified .I domain. .TP .I \-D Adds a "._domainkey" suffix to selector names in the zone file. .TP .I \-E secs When generating an SOA record (see .I \-S below), use .I secs as the default record expiration time. The default is 604800. .TP .I \-F Adds a "._domainkey" suffix and the domainname to selector names in the zone file. .TP .I \-N nslist Specifies a comma-separated list of nameservers, which will be output in NS records before the TXT records. The first nameserver in this list will also be used in the SOA record (if .I \-S is also specified) as the authority hostname. .TP .I \-o file Sends output to the named .I file rather than standard output. .TP .I \-r secs When generating an SOA record (see .I \-S below), use .I secs as the zone refresh time. The default is 10800. .TP .I \-R secs When generating an SOA record (see .I \-S below), use .I secs as the zone retry time. The default is 1800. .TP .I \-s Extends the logic of "-d" to include subdomains. .TP .I \-S Asks for an SOA record to be generated at the top of the output. The content of this output can be controlled using the .I \-E, .I \-r, .I \-R, .I \-T options. The serial number will be generated based on the current time of day. .TP .I \-t ttl Puts a TTL (time-to-live) value of .I ttl on all records output. The units are in seconds. .TP .I \-T secs When generating an SOA record (see .I \-S below), use .I secs as the default record TTL time. The default is 86400. .TP .I \-u Produce output suitable for use as input to .B nsupdate(8). .TP .I \-v Increases the verbosity of debugging output written to standard error. .TP .I \-x conffile Names an .I opendkim.conf(5) file to be read for LDAP-specific parameters when an LDAP dataset is given on the command line. Not required for other dataset types. The default is .I @SYSCONFDIR@/opendkim.conf. .SH VERSION This man page covers the version of .I opendkim-genzone that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2010, 2012, 2014, 2015, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I nsupdate(8), .I opendkim(8), .I opendkim.conf(5) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-genzone.c000066400000000000000000000522551337314105200237110ustar00rootroot00000000000000/* ** Copyright (c) 2010-2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* openssl includes */ #ifdef USE_GNUTLS # include # include # include # include #else /* USE_GNUTLS */ # include # include # include # include #endif /* USE_GNUTLS */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ /* libopendkim includes */ #include /* opendkim includes */ #include "opendkim-db.h" #include "config.h" #include "opendkim-config.h" /* definitions */ #define BUFRSZ 1024 #define CMDLINEOPTS "C:d:DE:Fo:N:r:R:sSt:T:uvx:" #define DEFCONFFILE CONFIG_BASE "/opendkim.conf" #define DEFEXPIRE 604800 #define DEFREFRESH 10800 #define DEFRETRY 1800 #define DEFTTL 86400 #define DKIMZONE "._domainkey" #define HOSTMASTER "hostmaster" #define LARGEBUFRSZ 8192 #define MARGIN 75 #define MAXNS 16 /* globals */ char *progname; /* ** STRFLEN -- determine length of a formatted string ** ** Parameters: ** str -- string of interest ** ** Return value: ** Rendered width (i.e. expand tabs, etc.). */ int strflen(char *str) { int olen = 0; char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (*p == '\t') olen += 8 - (olen % 8); else olen++; } return olen; } /* ** LOADKEY -- resolve a key ** ** Parameters: ** buf -- key buffer ** buflen -- pointer to key buffer's length (updated) ** ** Return value: ** TRUE on successful load, false otherwise */ int loadkey(char *buf, size_t *buflen) { assert(buf != NULL); assert(buflen != NULL); if (buf[0] == '/' || (buf[0] == '.' && buf[1] == '/') || (buf[0] == '.' && buf[1] == '.' && buf[2] == '/')) { int fd; int status; ssize_t rlen; struct stat s; fd = open(buf, O_RDONLY); if (fd < 0) return FALSE; status = fstat(fd, &s); if (status != 0) { close(fd); return FALSE; } *buflen = MIN(s.st_size, *buflen); rlen = read(fd, buf, *buflen); close(fd); if (rlen < *buflen) return FALSE; } else { *buflen = strlen(buf); } return TRUE; } /* ** DESPACE -- remove spaces from a string ** ** Parameters: ** str -- string to update ** ** Return value: ** None. */ void despace(char *str) { char *p; char *q; assert(str != NULL); for (p = str, q = str; ; p++) { if (isascii(*p) && isspace(*p)) continue; else *q++ = *p; if (*p == '\0') break; } } /* ** USAGE -- print usage message and exit ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [opts] [dataset]\n" "\t-C user@host\tcontact address to include in SOA\n" "\t-d domain \twrite keys for named domain only\n" "\t-D \tinclude '._domainkey' suffix\n" "\t-E secs \tuse specified expiration time in SOA\n" "\t-F \tinclude '._domainkey' suffix and domainname\n" "\t-o file \toutput file\n" "\t-N ns[,...] \tlist NS records\n" "\t-r secs \tuse specified refresh time in SOA\n" "\t-R secs \tuse specified retry time in SOA\n" "\t-s \twith -d, also match subdomains\n" "\t-S \twrite an SOA record\n" "\t-t secs \tuse specified per-record TTL\n" "\t-T secs \tuse specified default TTL in SOA\n" "\t-u \tproduce output suitable for use by \"nsupdate\"\n" "\t-v \tverbose output\n" "\t-x file \tconfiguration file\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { _Bool seenlf; _Bool nsupdate = FALSE; _Bool suffix = FALSE; _Bool fqdnsuffix = FALSE; _Bool subdomains = FALSE; _Bool writesoa = FALSE; int c; int status; int verbose = 0; int olen; int ttl = -1; int defttl = DEFTTL; int expire = DEFEXPIRE; int refresh = DEFREFRESH; int retry = DEFRETRY; int nscount = 0; long len; time_t now; size_t keylen; size_t domain_len; size_t onlydomain_len; char *p; char *dataset = NULL; char *outfile = NULL; char *onlydomain = NULL; char *contact = NULL; char *nameservers = NULL; char *configfile = NULL; char *err = NULL; char *nslist[MAXNS]; FILE *out; #ifdef USE_GNUTLS gnutls_x509_privkey_t xprivkey; gnutls_privkey_t privkey; gnutls_pubkey_t pubkey; gnutls_datum_t key; #else /* USE_GNUTLS */ BIO *private; BIO *outbio = NULL; EVP_PKEY *pkey; RSA *rsa; #endif /* USE_GNUTLS */ DKIMF_DB db; char keyname[BUFRSZ + 1]; char domain[BUFRSZ + 1]; char selector[BUFRSZ + 1]; char tmpbuf[BUFRSZ + 1]; char hostname[DKIM_MAXHOSTNAMELEN + 1]; char keydata[LARGEBUFRSZ]; char derdata[LARGEBUFRSZ]; struct dkimf_db_data dbd[3]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) { switch (c) { case 'C': contact = strdup(optarg); break; case 'd': onlydomain = optarg; break; case 'D': suffix = TRUE; break; case 'E': expire = strtol(optarg, &p, 10); if (*p != '\0' || expire < 0) { fprintf(stderr, "%s: invalid expire value\n", progname); return EX_USAGE; } break; case 'F': suffix = TRUE; fqdnsuffix = TRUE; break; case 'N': nameservers = strdup(optarg); break; case 'o': outfile = optarg; break; case 'r': refresh = strtol(optarg, &p, 10); if (*p != '\0' || refresh < 0) { fprintf(stderr, "%s: invalid refresh value\n", progname); return EX_USAGE; } break; case 'R': retry = strtol(optarg, &p, 10); if (*p != '\0' || retry < 0) { fprintf(stderr, "%s: invalid retry value\n", progname); return EX_USAGE; } break; case 's': subdomains = TRUE; break; case 'S': writesoa = TRUE; break; case 't': ttl = strtol(optarg, &p, 10); if (*p != '\0' || ttl < 0) { fprintf(stderr, "%s: invalid TTL value\n", progname); return EX_USAGE; } break; case 'T': defttl = strtol(optarg, &p, 10); if (*p != '\0' || defttl < 0) { fprintf(stderr, "%s: invalid default TTL value\n", progname); return EX_USAGE; } break; case 'u': nsupdate = TRUE; break; case 'v': verbose++; break; case 'x': configfile = optarg; break; default: return usage(); } } /* sanity check */ if (subdomains && onlydomain == NULL) { fprintf(stderr, "%s: subdomain matching requires a domain\n", progname); return EX_USAGE; } if (optind != argc) dataset = argv[optind]; /* process config file */ if (configfile == NULL && access(DEFCONFFILE, R_OK) == 0) configfile = DEFCONFFILE; if (configfile != NULL) { #ifdef USE_LDAP _Bool ldap_usetls = FALSE; #endif /* USE_LDAP */ u_int line = 0; #ifdef USE_LDAP char *ldap_authmech = NULL; # ifdef USE_SASL char *ldap_authname = NULL; char *ldap_authrealm = NULL; char *ldap_authuser = NULL; # endif /* USE_SASL */ char *ldap_bindpw = NULL; char *ldap_binduser = NULL; #endif /* USE_LDAP */ struct config *cfg; char path[MAXPATHLEN + 1]; cfg = config_load(configfile, dkimf_config, &line, path, sizeof path, NULL); if (cfg == NULL) { fprintf(stderr, "%s: %s: configuration error at line %u\n", progname, path, line); return EX_CONFIG; } if (dataset == NULL) { (void) config_get(cfg, "KeyTable", &dataset, sizeof dataset); } #ifdef USE_LDAP (void) config_get(cfg, "LDAPUseTLS", &ldap_usetls, sizeof ldap_usetls); if (ldap_usetls) dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "y"); else dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "n"); (void) config_get(cfg, "LDAPAuthMechanism", &ldap_authmech, sizeof ldap_authmech); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHMECH, ldap_authmech); # ifdef USE_SASL (void) config_get(cfg, "LDAPAuthName", &ldap_authname, sizeof ldap_authname); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHNAME, ldap_authname); (void) config_get(cfg, "LDAPAuthRealm", &ldap_authrealm, sizeof ldap_authrealm); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHREALM, ldap_authrealm); (void) config_get(cfg, "LDAPAuthUser", &ldap_authuser, sizeof ldap_authuser); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHUSER, ldap_authuser); # endif /* USE_SASL */ (void) config_get(cfg, "LDAPBindPassword", &ldap_bindpw, sizeof ldap_bindpw); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDPW, ldap_bindpw); (void) config_get(cfg, "LDAPBindUser", &ldap_binduser, sizeof ldap_binduser); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDUSER, ldap_binduser); #endif /* USE_LDAP */ } if (dataset == NULL) return usage(); #ifndef USE_GNUTLS outbio = BIO_new(BIO_s_mem()); if (outbio == NULL) { fprintf(stderr, "%s: BIO_new() failed\n", progname); return 1; } #endif /* ! USE_GNUTLS */ #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ status = dkimf_db_open(&db, dataset, DKIMF_DB_FLAG_READONLY, NULL, &err); if (status != 0) { fprintf(stderr, "%s: dkimf_db_open(): %s\n", progname, err); #ifndef USE_GNUTLS (void) BIO_free(outbio); #endif /* ! USE_GNUTLS */ return 1; } if (dkimf_db_type(db) == DKIMF_DB_TYPE_REFILE) { fprintf(stderr, "%s: invalid data set type\n", progname); #ifndef USE_GNUTLS (void) BIO_free(outbio); #endif /* ! USE_GNUTLS */ (void) dkimf_db_close(db); return 1; } if (verbose > 0) fprintf(stderr, "%s: database opened\n", progname); if (outfile != NULL) { out = fopen(outfile, "w"); if (out == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, outfile, strerror(errno)); (void) dkimf_db_close(db); #ifndef USE_GNUTLS (void) BIO_free(outbio); #endif /* ! USE_GNUTLS */ return 1; } } else { out = stdout; } if (nameservers != NULL) { for (p = strtok(nameservers, ","); p != NULL && nscount < MAXNS; p = strtok(NULL, ",")) nslist[nscount++] = p; } memset(hostname, '\0', sizeof hostname); gethostname(hostname, sizeof hostname); if (nscount == 0) nslist[nscount++] = hostname; (void) time(&now); if (!nsupdate) { fprintf(out, "; DKIM public key zone data\n"); if (onlydomain != NULL) fprintf(out, "; for %s\n", onlydomain); fprintf(out, "; auto-generated by %s at %s\n", progname, ctime(&now)); } if (writesoa && !nsupdate) { struct tm *tm; fprintf(out, "@\tIN\tSOA\t%s\t", nslist[0]); if (contact != NULL) { for (p = contact; *p != '\0'; p++) { if (*p == '@') *p = '.'; } fprintf(out, "%s", contact); } else { struct passwd *pwd; pwd = getpwuid(getuid()); fprintf(out, "%s.%s", pwd == NULL ? HOSTMASTER : pwd->pw_name, hostname); } tm = localtime(&now); fprintf(out, "\t (\n" "\t%04d%02d%02d%02d ; Serial (yyyymmddhh)\n" "\t%-10d ; Refresh\n" "\t%-10d ; Retry\n" "\t%-10d ; Expire\n" "\t%-10d ) ; Default\n\n", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, refresh, retry, expire, defttl); } if (nameservers != NULL && !nsupdate) { for (c = 0; c < nscount; c++) fprintf(out, "\tIN\tNS\t%s\n", nslist[c]); fprintf(out, "\n"); } if (nsupdate) fprintf(out, "server %s\n", nslist[0]); dbd[0].dbdata_buffer = domain; dbd[1].dbdata_buffer = selector; dbd[2].dbdata_buffer = keydata; for (c = 0; ; c++) { memset(keyname, '\0', sizeof keyname); memset(domain, '\0', sizeof domain); memset(selector, '\0', sizeof selector); memset(keydata, '\0', sizeof keydata); dbd[0].dbdata_buflen = sizeof domain; dbd[1].dbdata_buflen = sizeof selector; dbd[2].dbdata_buflen = sizeof keydata; keylen = sizeof keyname; status = dkimf_db_walk(db, c == 0, keyname, &keylen, dbd, 3); if (status == -1) { char err[BUFRSZ]; dkimf_db_strerror(db, err, sizeof err); fprintf(stderr, "%s: dkimf_db_walk(%d) failed: %s\n", progname, c, err); (void) dkimf_db_close(db); #ifndef USE_GNUTLS (void) BIO_free(outbio); #endif /* ! USE_GNUTLS */ return 1; } else if (status == 1) { break; } if (subdomains) { domain_len = strlen(domain); onlydomain_len = strlen(onlydomain); if ((domain_len == onlydomain_len && strcasecmp(domain, onlydomain) == 0) || (domain_len > onlydomain_len && domain[domain_len - onlydomain_len - 1] == '.' && strcasecmp(domain + domain_len - onlydomain_len, onlydomain) == 0)) { fprintf(stderr, "%s: record %d for '%s' skipped\n", progname, c, keyname); continue; } } else { if (onlydomain != NULL && strcasecmp(domain, onlydomain) != 0) { fprintf(stderr, "%s: record %d for '%s' skipped\n", progname, c, keyname); continue; } } if (verbose > 1) { fprintf(stderr, "%s: record %d for '%s' retrieved\n", progname, c, keyname); } keylen = sizeof keydata; if (!loadkey(keydata, &keylen)) { fprintf(stderr, "%s: key for '%s' load failed\n", progname, keyname); (void) dkimf_db_close(db); #ifndef USE_GNUTLS (void) BIO_free(outbio); #endif /* USE_GNUTLS */ return 1; } if (verbose > 1) { fprintf(stderr, "%s: key for '%s' loaded\n", progname, keyname); } #ifdef USE_GNUTLS if (gnutls_x509_privkey_init(&xprivkey) != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_x509_privkey_init() failed\n", progname); (void) dkimf_db_close(db); return 1; } key.data = keydata; key.size = keylen; status = gnutls_x509_privkey_import(xprivkey, &key, GNUTLS_X509_FMT_PEM); if (status != GNUTLS_E_SUCCESS) { status = gnutls_x509_privkey_import(xprivkey, &key, GNUTLS_X509_FMT_DER); } if (status != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_x509_privkey_import() failed\n", progname); (void) gnutls_x509_privkey_deinit(xprivkey); return -1; } status = gnutls_privkey_init(&privkey); if (status != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_privkey_init() failed\n", progname); (void) gnutls_x509_privkey_deinit(xprivkey); return -1; } status = gnutls_privkey_import_x509(privkey, xprivkey, 0); if (status != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_privkey_import_x509() failed\n", progname); (void) gnutls_x509_privkey_deinit(xprivkey); (void) gnutls_privkey_deinit(privkey); return -1; } #else /* USE_GNUTLS */ /* create a BIO for the private key */ if (strncmp(keydata, "-----", 5) == 0) { private = BIO_new_mem_buf(keydata, keylen); if (private == NULL) { fprintf(stderr, "%s: BIO_new_mem_buf() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(outbio); return 1; } pkey = PEM_read_bio_PrivateKey(private, NULL, NULL, NULL); if (pkey == NULL) { fprintf(stderr, "%s: PEM_read_bio_PrivateKey() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(private); (void) BIO_free(outbio); return 1; } } else { int inlen; int outlen; BIO *b64; BIO *bio; BIO *decode; char buf[BUFRSZ]; despace(keydata); b64 = BIO_new(BIO_f_base64()); BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bio = BIO_new_mem_buf(keydata, -1); bio = BIO_push(b64, bio); decode = BIO_new(BIO_s_mem()); for (;;) { inlen = BIO_read(bio, buf, sizeof buf); if (inlen == 0) break; BIO_write(decode, buf, inlen); } BIO_flush(decode); outlen = BIO_get_mem_data(decode, &p); memcpy(derdata, p, MIN(sizeof derdata, outlen)); BIO_free_all(b64); BIO_free(decode); private = BIO_new_mem_buf(derdata, outlen); if (private == NULL) { fprintf(stderr, "%s: BIO_new_mem_buf() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(outbio); return 1; } pkey = d2i_PrivateKey_bio(private, NULL); if (pkey == NULL) { fprintf(stderr, "%s: d2i_PrivateKey_bio() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(private); (void) BIO_free(outbio); return 1; } } rsa = EVP_PKEY_get1_RSA(pkey); if (rsa == NULL) { fprintf(stderr, "%s: EVP_PKEY_get1_RSA() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(private); (void) EVP_PKEY_free(pkey); (void) BIO_free(outbio); return 1; } /* convert private to public */ status = PEM_write_bio_RSA_PUBKEY(outbio, rsa); if (status == 0) { fprintf(stderr, "%s: PEM_write_bio_RSA_PUBKEY() failed\n", progname); (void) dkimf_db_close(db); (void) BIO_free(private); (void) EVP_PKEY_free(pkey); (void) BIO_free(outbio); return 1; } #endif /* USE_GNUTLS */ /* write the record */ if (nsupdate) { fprintf(out, "zone %s\n", domain); snprintf(tmpbuf, sizeof tmpbuf, "update add %s%s%s%s%s %d TXT \"", selector, suffix ? DKIMZONE : "", fqdnsuffix ? "." : "", fqdnsuffix ? domain : "", fqdnsuffix ? "." : "", ttl == -1 ? defttl : ttl); } else { if (ttl == -1) { snprintf(tmpbuf, sizeof tmpbuf, "%s%s%s%s%s\tIN\tTXT\t( \"v=DKIM1; k=rsa; p=", selector, suffix ? DKIMZONE : "", fqdnsuffix ? "." : "", fqdnsuffix ? domain : "", fqdnsuffix ? "." : ""); } else { snprintf(tmpbuf, sizeof tmpbuf, "%s%s%s%s%s\t%d\tIN\tTXT\t( \"v=DKIM1; k=rsa; p=", selector, suffix ? DKIMZONE : "", fqdnsuffix ? "." : "", fqdnsuffix ? domain : "", fqdnsuffix ? "." : "", ttl); } } fprintf(out, "%s", tmpbuf); if (nsupdate) olen = 0; else olen = strflen(tmpbuf); seenlf = FALSE; #ifdef USE_GNUTLS if (gnutls_pubkey_init(&pubkey) != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_pubkey_init() failed\n", progname); (void) dkimf_db_close(db); (void) gnutls_x509_privkey_deinit(xprivkey); return 1; } if (gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, 0) != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_pubkey_import_privkey() failed\n", progname); (void) dkimf_db_close(db); (void) gnutls_x509_privkey_deinit(xprivkey); (void) gnutls_pubkey_deinit(pubkey); return 1; } keylen = sizeof keydata; if (gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_PEM, keydata, &keylen) != GNUTLS_E_SUCCESS) { fprintf(stderr, "%s: gnutls_pubkey_export() failed\n", progname); (void) dkimf_db_close(db); (void) gnutls_x509_privkey_deinit(xprivkey); return 1; } for (len = keylen, p = keydata; len > 0; len--, p++) #else /* USE_GNUTLS */ for (len = BIO_get_mem_data(outbio, &p); len > 0; len--, p++) #endif /* USE_GNUTLS */ { if (*p == '\n') { seenlf = TRUE; } else if (seenlf && *p == '-') { break; } else if (!seenlf) { continue; } else if (isascii(*p) && !isspace(*p)) { if (olen >= MARGIN && !nsupdate) { fprintf(out, "\"\n\t\""); olen = 9; } else if (olen >= 255 && nsupdate) { fprintf(out, "\" \""); olen = 0; } (void) fputc(*p, out); olen++; } } if (nsupdate) fprintf(out, "\"\n"); else fprintf(out, "\" )\n"); /* prepare for the next one */ #ifdef USE_GNUTLS (void) gnutls_x509_privkey_deinit(xprivkey); (void) gnutls_privkey_deinit(privkey); (void) gnutls_pubkey_deinit(pubkey); #else /* USE_GNUTLS */ (void) BIO_reset(outbio); #endif /* USE_GNUTLS */ } #ifndef USE_GNUTLS (void) BIO_flush(outbio); (void) BIO_free(outbio); #endif /* ! USE_GNUTLS */ (void) dkimf_db_close(db); if (nsupdate) fprintf(out, "send\nanswer\n"); if (out != stdout) fclose(out); if (verbose > 0) { fprintf(stdout, "%s: %d record%s written\n", progname, c, c == 1 ? "" : "s"); } return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-lua.3.in000066400000000000000000000436521337314105200233530ustar00rootroot00000000000000.TH opendkim-lua 3 "The Trusted Domain Project" .SH NAME .B opendkim-lua \- Programming the OpenDKIM filter using Lua scripts .SH DESCRIPTION The OpenDKIM filter has hooks to run user-provided scripts for making policy decisions regarding signatures to add on outbound messages or verification and acceptance of messages inbound. The hooks take the form of multiple Lua scripts which, if defined, are run at important points during processing of a message. For a full description of the Lua language, consult Lua programming references (see below for a starting point). This man page only describes the use of Lua in the context of OpenDKIM, specifically the functions and global variables OpenDKIM provides for use in user-constructed scripts beyond what Lua provides by default. Unless otherwise noted, all functions described below return a single result; on success they return the requested data, and on error they return the Lua constant "nil". Four scripting hooks are provided. They are as follows: .TP .I setup The setup script is run after all headers for the message have been received but before any DKIM operations have started. At this point the user can examine the available header fields to decide whether the message should be signed or verified (or both) and, if signing, which key(s) should be used to add signatures and which signature features are desired. .TP .I screen The screen script is run after the DKIM verification context has been established. The main purpose of this script is to give the user an opportunity to examine the message header fields compared to the available DKIM signatures and determine which, if any, should be ignored during verification. For example, the user might decide only signatures added by domains exactly matching that in the From: domain are acceptable, and the rest should be ignored. .TP .I statistics The statistics script is run after all of the DKIM verification and signing work has been completed but before any final message handling is done. The main purpose of this script is to give the user an opportunity to examine the message or its signatures and make arbitrary additional statistical observations that should be recorded by the statistics module. @STATSEXT_MANNOTICE@ .TP .I final The final script is run after all of the DKIM verification and signing work has been completed. The user has an opportunity to examine the results of all of the signature evaluations and make a decision about whether or not the message should be accepted, rejected, discarded, quarantined, etc. If the message is accepted, any signatures requested earlier will be added to the messages before it is released. .SH GLOBAL VARIABLES The following global variable(s) are provided for all user scripts: .TP .I ctx This is a generic context pointer referring to the context in which the filtering operation is being performed. It represents a single message in progress, and the connection that accepted it. .SH SETUP SCRIPT FUNCTIONS These functions are made available to Lua for processing a message through the setup script: .TP .B odkim.check_popauth(ctx) Returns 1 if the SMTP client represented by .I ctx is coming from an IP address found in the POPAUTH database (if enabled and configured), and 0 otherwise. Returns the Lua constant "nil" if the POPAUTH database is not enabled or not configured. .TP .B odkim.db_check(db, string) Returns 1 if .I db refers to a valid database handle (see .B odkim.get_dbhandle() below) and .I string is found in that database, and 0 otherwise. If an error occurs, the Lua constant "nil" is returned. .TP .B odkim.db_close(db) Closes the specified data set. Returns 1. The current implementation will conduct data set garbage collection when the script terminates, so this is not strictly necessary, but is recommended. .TP .B odkim.db_open(name[, icase]) Opens the data set specified by .I name. If .I icase is provided and is "true", then queries into the database will be case-insensitive. See the .I opendkim(8) man page for information on specifying a data set. On success, returns a handle that can be passed to .B odkim.db_check(); raises an exception on failure. .TP .B odkim.export(ctx, name, value[, name2, value2[, ...]]) Exports variables named with their corresponding values so that they will be available to later scripts. .TP .B odkim.get_clienthost(ctx) Returns the name of the host on the other end of the SMTP connection sending the current message. This is usually a hostname, but might be an IP address in square brackets if the SMTP client's IP address does not have a name associated with it. .TP .B odkim.get_clientip(ctx) Returns the IP address of the client on the other end of the SMTP connection sending the current message as a string. Both IPv4 and IPv6 addresses are supported. .TP .B odkim.get_dbhandle(ctx, db) Returns a handle for the requested database that can be used in later queries. The value of .I db should be one of .I DB_MTAS (database of MTA names whose mail should be signed), .I DB_MACROS (database of MTA macro checks to be done when determining signing), .I DB_DOMAINS (database of domains to be signed), .I DB_SIGNINGTABLE (database of signing table entries), .I DB_THIRDPARTY (database of third party signatures to be trusted) and .I DB_DONTSIGNTO (database of recipients whose mail should not be signed). If the requested database is not set in the current configuration file, a Lua "nil" is returned. .TP .B odkim.get_envfrom(ctx) Retrieves the SMTP envelope sender address for the message represented by .I ctx. .TP .B odkim.get_fromdomain(ctx) Retrieves the domain name of the sender of the message represented by .I ctx. .TP .B odkim.get_header(ctx, name, n) Retrieves the string contained in instance .I n of the header field called .I name from the message represented by .I ctx, or the Lua constant "nil" if there was no such header field. Header field numbering starts at 0, so use 0 for the first instance, 1 for the second, etc. For example: fromaddr = odkim.get_header(ctx, "From", 0) This will return the value of the first (and hopefully only) "From" header field. Negative values of .I n count backwards from the end of the set of header fields, so: rcvd = odkim.get_header(ctx, "Received", \-2) will retrieve the second-last Received: header field on the message. .TP .B odkim.get_mtasymbol(ctx, name) Retrieves the value of the symbol called .I name from the MTA connection represented by .I ctx, or the Lua constant "nil" if the requested symbol was not available at the time of the request. .TP .B odkim.get_rcpt(ctx, n) Returns the .I nth envelope recipient for the message represented by .I ctx. Recipient numbering starts at 0, so for the first recipient, use 0 for .I n. If .I n references an out-of-range value, the Lua constant "nil" is returned. .TP .B odkim.get_rcptarray(ctx) Returns the envelope recipients for the message represented by .I ctx in a single Lua array. .TP .B odkim.internal_ip(ctx) Returns 1 if the SMTP client is coming from an internal IP address, and 0 otherwise. .TP .B odkim.log(ctx, log) Logs the string .I log if the current configuration requested logging. (Checking current configuration is why the .I ctx parameter is required.) .TP .B odkim.rcpt_count(ctx) Returns the count of envelope recipients on the message. .TP .B odkim.replace_header(ctx, name, n, newval) Retrieves the value of in instance .I n of header field .I name in the message referenced by .I ctx and replaces it with the string in .I newval. See .I odkim.get_header() above for more information about possible parameter values for .I n. Note that this only changes the content of the header field used when generating or verifying the signature; the actual delivered message is not modified. This can be used to anticipate how an intermediate mail transfer agent might alter the message, thus correcting an avoidable signature invalidation. .TP .B odkim.resign(ctx) Arranges that the arriving message will be verified and then re-signed in a single operation. Returns 1 on success or the Lua constant "nil" on failure. .TP .B odkim.set_result(ctx, result) Arranges to have the MTA return a specific result code in response to the message represented by .I ctx. The value of .I result must be one of .I SMFIS_TEMPFAIL (temporary failure/rejection), .I SMFIS_ACCEPT (accept without further processing), .I SMFIS_DISCARD (accept but discard the message) and .I SMFIS_REJECT (permanent failure/rejection). Returns 1 on success or the Lua constant "nil" on failure. Note that returning any of these codes indicates a final message disposition; the MTA will be told immediately to take the specified action, and no further filter processing will occur. .TP .B odkim.sign(ctx[, keyname[, signer[, signlen]]]) Requests that the filter sign the message represented by .I ctx using the specified .I keyname. The key name will be translated into an actual domain, selector and private key via a query to the KeyTable (see the .I opendkim.conf(5) page for details). The .I keyname may be omitted if the KeyTable is not defined, meaning the single signing domain, selector and key should be used to sign. Returns 1 on success and 0 on failure. If a .I signer is specified, the string there will be included in the generated signature's "i=" tag. If a .I signlen is specified, the signature will cover that many bytes of the message body. The order of these last two parameters is interchangeable. .TP .B odkim.signfor(ctx, address[, multi]) Applies whatever signatures would be applied by default if the candidate message had the specified .I address in the message's From: field. The .I multi parameter, if "true" (default is "false"), allows the application of multiple signatures. Returns the number of signatures applied, which may be zero. .TP .B odkim.spam(ctx) Tags the message as spam, for use in developing reputation about domains that signed the message. Returns nothing. @REPUTATION_MANNOTICE@ .TP .B odkim.use_ltag(ctx) Requests that all signatures added to the message represented by .I ctx include "l=" (body length) tags. Always returns the Lua constant "nil". .TP .B odkim.verify(ctx) Requests that the message represented by .I ctx be subjected to DKIM signature verification. Returns the Lua constant "nil" on success, or an error string on failure. .TP .B odkim.xtag(ctx, tag, value) Requests that all signatures added to the message represented by .I ctx include the named extension .I tag and .I value. Returns the number of signatures successfully modified, or \-1 on error. An error can occur if the named tag is one already explicitly supported by the DKIM library, or if there is a syntax error in the tag or value. .SH SCREEN SCRIPT FUNCTIONS The screen script has the following functions available to it, whose descriptions can be found above: .B odkim.db_check, .B odkim.db_close, .B odkim.db_open, .B odkim.export, .B odkim.get_dbhandle, .B odkim.get_envfrom, .B odkim.get_fromdomain, .B odkim.get_header, .B odkim.get_mtasymbol, .B odkim.get_rcpt, .B odkim.get_rcptarray, .B odkim.internal_ip, .B odkim.log, .B odkim.rcpt_count, and .B odkim.spam. The following additional functions are provided for this script: .TP .B odkim.get_sigarray(ctx) Returns the complete set of signature handles found in the message represented by .I ctx, as a Lua array, or the Lua constant "nil" in case of an error. .TP .B odkim.get_sigcount(ctx) Returns the number of signatures found in the message represented by .I ctx, or the Lua constant "nil" in case of an error. .TP .B odkim.get_sighandle(ctx, n) Returns a handle representing an internal copy of the .I nth signature found on the message represented by .I ctx. .I n must be a number greater than or equal to zero (representing the first signature) and less than the number of signatures on the message, which can be determined using .B odkim.get_sigcount above. The requested handle is returned on success, or the Lua constant "nil" is returned on failure. .TP .B odkim.parse_field(string) Parses the contents of a header field, provided as .I string, into user and domain parts, discarding whitespace and comment components. Returns two strings, the user part and the domain part, or the Lua constant "nil" in case of a parsing error. .TP .B odkim.sig_getdomain(sig) Returns the name of the domain in the signature handle specified by .I sig, previously returned by a call to .B odkim.get_sighandle(). This is taken from the signature's "d=" tag. .TP .B odkim.sig_getidentity(sig) Returns the identity of the agent adding the signature handle specified by .I sig, previously returned by a call to .B odkim.get_sighandle(). This is taken from the signature's "i=" tag. This may be a default value and not one that was explicitly part of the signature. If the identity could not be determined, the Lua constant "nil" is returned. .TP .B odkim.sig_ignore(sig) Instructs the verification code to ignore completely the signature specified by .I sig, previously returned by a call to .B odkim.get_sighandle(). Any pending verification of the message will act as if that signature was not present on the message. Always returns the Lua constant "nil". .SH STATISTICS SCRIPT FUNCTIONS The statistics script has the following functions available to it, whose descriptions can be found above: .B odkim.export, .B odkim.get_envfrom, .B odkim.get_header, .B odkim.get_mtasymbol, .B odkim.get_rcpt, .B odkim.get_rcptarray, .B odkim.get_sigarray, .B odkim.get_sigcount, .B odkim.get_sighandle, .B odkim.internal_ip, .B odkim.log, .B odkim.parse_field, .B odkim.rcpt_count, .B odkim.sig_getdomain, .B odkim.sig_getidentity, and .B odkim.spam. The following functions are also available, defined in the next section: .B odkim.rbl_check, .B odkim.rcpt_count, .B odkim.sig_bhresult, .B odkim.sig_bodylength, .B odkim.sig_canonlength, and .B odkim.sig_result. The following additional function is provided for this script: .TP .B odkim.stats(ctx, name, value) Records the additional statistic called .I name with its associated .I value for the message represented by .I ctx. .SH FINAL SCRIPT FUNCTIONS The final script has the following functions available to it, whose descriptions can be found above: .B odkim.get_clienthost, .B odkim.get_clientip, .B odkim.get_envfrom, .B odkim.get_fromdomain, .B odkim.get_header, .B odkim.get_mtasymbol, .B odkim.get_rcpt, .B odkim.get_rcptarray, .B odkim.get_sigarray, .B odkim.get_sigcount, .B odkim.get_sighandle, .B odkim.internal_ip, .B odkim.log, .B odkim.parse_field, .B odkim.rcpt_count, .B odkim.set_result, .B odkim.sig_getdomain, .B odkim.sig_getidentity, .B odkim.spam, and .B odkim.xtags. The following additional functions are provided for this script: .TP .B odkim.add_header(ctx, name, value) Adds a new header field called .I name with the specified .I value to the message represented by .I ctx. Returns 1 on success, or the Lua constant "nil" on failure. .TP .B odkim.add_rcpt(ctx, addr) Adds .I addr as an envelope recipient to the message represented by .I ctx. Returns 1 on success, or the Lua constant "nil" on failure. .TP .B odkim.del_header(ctx, name, n) Deletes the .I nth instance (starting from 0) of the header field called .I name from the message represented by .I ctx. Returns 1 on success, or the Lua constant "nil" on failure. .TP .B odkim.del_rcpt(ctx, addr) Deletes .I addr from the list of envelope recipients on the message represented by .I ctx, and adds a new X-Original-Recipient: header field containing the deleted address. Returns 1 on success, or the Lua constant "nil" on failure. .TP .B odkim.quarantine(ctx, reason) Asks the MTA to quarantine the message represented by .I ctx using .I reason as a text string indicating the reason for the request. Returns 1 on success or the Lua constant "nil" on failure. .TP .B odkim.rbl_check(ctx, query, qroot[, timeout]) Makes an RBL query. The root of the RBL is assumed to be at .I qroot and the subject of the query is .I query, so the query performed will be .I "query.qroot". The context handle .I ctx must also be provided as it contains a handle to the established DNS service. The optional .I timeout parameter is the timeout to use, in seconds. Returns "nil" on error, no values if the requested record was not present in the RBL, or the four octets of the RBL entry if it was. The octets are returned in big-endian order. @RBL_MANNOTICE@ .TP .B odkim.set_reply(ctx, rcode, xcode, message) Instructs the MTA to return the specified SMTP reply to the client sending the message represented by .I ctx. .I rcode must be a three-digit SMTP reply code starting with 4 or 5 (for temporary or permanent failures, respectively); .I xcode must be the empty string or a valid extended reply code (see RFC2034) matching .I rcode; and .I message must be the text portion of the SMTP reply to be sent. Returns 1 on success or the Lua constant "nil" on failure. .TP .B odkim.sig_bhresult(sig) Returns the result code corresponding to the body hash evaluation of the signature handled specified by .I sig, previously returned by a call to .B odkim.get_sighandle(). Valid values are the DKIM_SIGBH_* constants defined in the .B libopendkim header file .I dkim.h. .TP .B odkim.sig_bodylength(sig) Returns the total length of the message signed by .I sig, previously returned by a call to .B odkim.get_sighandle(), or the Lua constant "nil" if this value could not be determined. .TP .B odkim.sig_canonlength(sig) Returns the canonicalized length of the message signed by .I sig, previously returned by a call to .B odkim.get_sighandle(), or the Lua constant "nil" if this value could not be determined. Note that this may be less than the value returned by .B odkim.get_bodylength() if the signature only covered part of the message. .TP .B odkim.sig_result(sig) Returns the result code corresponding to the signature handled specified by .I sig, previously returned by a call to .B odkim.get_sighandle(). Valid values are the constants with DKIM_SIGERROR_ prefixes as defined in the .B libopendkim header file .I dkim.h. .SH VERSION This man page covers version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim.conf(5) .P Lua -- http://www.lua.org OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-lua.c000066400000000000000000001025411337314105200230170ustar00rootroot00000000000000/* ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" #ifdef USE_LUA /* system includes */ #include #include #include #include #include /* Lua includes */ #include #include #include /* libopendkim includes */ #include /* opendkim includes */ #define DKIMF_LUA_PROTOTYPES #define DKIMF_MILTER_PROTOTYPES #include "opendkim-lua.h" #include "opendkim-db.h" #include "opendkim.h" /* local data types */ struct dkimf_lua_io { _Bool lua_io_done; const char * lua_io_script; size_t lua_io_len; size_t lua_io_alloc; }; #ifdef DKIMF_LUA_CONTEXT_HOOKS /* libraries */ static const luaL_Reg dkimf_lua_lib_setup[] = { { "check_popauth", dkimf_xs_popauth }, { "db_check", dkimf_xs_dbquery }, { "db_close", dkimf_xs_dbclose }, { "db_open", dkimf_xs_dbopen }, { "export", dkimf_xs_export }, { "get_clienthost", dkimf_xs_clienthost }, { "get_clientip", dkimf_xs_clientip }, { "get_dbhandle", dkimf_xs_dbhandle }, { "get_envfrom", dkimf_xs_getenvfrom }, { "get_fromdomain", dkimf_xs_fromdomain }, { "get_header", dkimf_xs_getheader }, { "get_mtasymbol", dkimf_xs_getsymval }, { "get_rcpt", dkimf_xs_rcpt }, { "get_rcptarray", dkimf_xs_rcptarray }, { "internal_ip", dkimf_xs_internalip }, { "log", dkimf_xs_log }, { "rcpt_count", dkimf_xs_rcptcount }, { "replace_header", dkimf_xs_replaceheader }, { "resign", dkimf_xs_resign }, { "set_result", dkimf_xs_setresult }, { "sign", dkimf_xs_requestsig }, { "signfor", dkimf_xs_signfor }, #ifdef _FFR_REPUTATION { "spam", dkimf_xs_spam }, #endif /* _FFR_REPUTATION */ { "use_ltag", dkimf_xs_setpartial }, { "verify", dkimf_xs_verify }, { "xtag", dkimf_xs_xtag }, { NULL, NULL } }; static const luaL_Reg dkimf_lua_lib_screen[] = { { "db_check", dkimf_xs_dbquery }, { "db_close", dkimf_xs_dbclose }, { "db_open", dkimf_xs_dbopen }, { "export", dkimf_xs_export }, { "get_dbhandle", dkimf_xs_dbhandle }, { "get_envfrom", dkimf_xs_getenvfrom }, { "get_fromdomain", dkimf_xs_fromdomain }, { "get_header", dkimf_xs_getheader }, { "get_mtasymbol", dkimf_xs_getsymval }, { "get_rcpt", dkimf_xs_rcpt }, { "get_rcptarray", dkimf_xs_rcptarray }, { "get_sigarray", dkimf_xs_getsigarray }, { "get_sigcount", dkimf_xs_getsigcount }, { "get_sighandle", dkimf_xs_getsighandle }, { "internal_ip", dkimf_xs_internalip }, { "log", dkimf_xs_log }, { "parse_field", dkimf_xs_parsefield }, { "rcpt_count", dkimf_xs_rcptcount }, { "sig_getdomain", dkimf_xs_getsigdomain }, { "sig_getidentity", dkimf_xs_getsigidentity }, { "sig_ignore", dkimf_xs_sigignore }, #ifdef _FFR_REPUTATION { "spam", dkimf_xs_spam }, #endif /* _FFR_REPUTATION */ { NULL, NULL } }; # ifdef _FFR_STATSEXT static const luaL_Reg dkimf_lua_lib_stats[] = { { "export", dkimf_xs_export }, { "get_envfrom", dkimf_xs_getenvfrom }, { "get_header", dkimf_xs_getheader }, { "get_mtasymbol", dkimf_xs_getsymval }, { "get_rcpt", dkimf_xs_rcpt }, { "get_rcptarray", dkimf_xs_rcptarray }, { "get_sigarray", dkimf_xs_getsigarray }, { "get_sigcount", dkimf_xs_getsigcount }, { "get_sighandle", dkimf_xs_getsighandle }, { "internal_ip", dkimf_xs_internalip }, { "log", dkimf_xs_log }, { "parse_field", dkimf_xs_parsefield }, # ifdef _FFR_RBL { "rbl_check", dkimf_xs_rblcheck }, # endif /* _FFR_RBL */ { "rcpt_count", dkimf_xs_rcptcount }, { "sig_bhresult", dkimf_xs_sigbhresult }, { "sig_bodylength", dkimf_xs_bodylength }, { "sig_canonlength", dkimf_xs_canonlength }, { "sig_getdomain", dkimf_xs_getsigdomain }, { "sig_getidentity", dkimf_xs_getsigidentity }, { "sig_result", dkimf_xs_sigresult }, { "stats", dkimf_xs_statsext }, #ifdef _FFR_REPUTATION { "spam", dkimf_xs_spam }, #endif /* _FFR_REPUTATION */ { NULL, NULL } }; # endif /* _FFR_STATSEXT */ static const luaL_Reg dkimf_lua_lib_final[] = { { "add_header", dkimf_xs_addheader }, { "add_rcpt", dkimf_xs_addrcpt }, { "del_header", dkimf_xs_delheader }, { "del_rcpt", dkimf_xs_delrcpt }, { "get_clienthost", dkimf_xs_clienthost }, { "get_clientip", dkimf_xs_clientip }, { "get_envfrom", dkimf_xs_getenvfrom }, { "get_fromdomain", dkimf_xs_fromdomain }, { "get_header", dkimf_xs_getheader }, { "get_mtasymbol", dkimf_xs_getsymval }, { "get_rcpt", dkimf_xs_rcpt }, { "get_rcptarray", dkimf_xs_rcptarray }, { "get_sigarray", dkimf_xs_getsigarray }, { "get_sigcount", dkimf_xs_getsigcount }, { "get_sighandle", dkimf_xs_getsighandle }, { "internal_ip", dkimf_xs_internalip }, { "log", dkimf_xs_log }, { "quarantine", dkimf_xs_quarantine }, { "parse_field", dkimf_xs_parsefield }, # ifdef _FFR_RBL { "rbl_check", dkimf_xs_rblcheck }, # endif /* _FFR_RBL */ { "rcpt_count", dkimf_xs_rcptcount }, { "set_reply", dkimf_xs_setreply }, { "set_result", dkimf_xs_setresult }, { "sig_bhresult", dkimf_xs_sigbhresult }, { "sig_bodylength", dkimf_xs_bodylength }, { "sig_canonlength", dkimf_xs_canonlength }, { "sig_getdomain", dkimf_xs_getsigdomain }, { "sig_getidentity", dkimf_xs_getsigidentity }, { "sig_result", dkimf_xs_sigresult }, # ifdef _FFR_REPUTATION { "spam", dkimf_xs_spam }, # endif /* _FFR_REPUTATION */ { "xtag", dkimf_xs_xtag }, { NULL, NULL } }; #endif /* DKIMF_LUA_CONTEXT_HOOKS */ /* ** DKIMF_LUA_READER -- "read" a script and make it available to Lua ** ** Parameters: ** l -- Lua state ** data -- pointer to a Lua I/O structure ** size -- size (returned) ** ** Return value: ** Pointer to the data. */ static const char * dkimf_lua_reader(lua_State *l, void *data, size_t *size) { struct dkimf_lua_io *io; assert(l != NULL); assert(data != NULL); assert(size != NULL); io = (struct dkimf_lua_io *) data; if (io->lua_io_done) { *size = 0; return NULL; } else { io->lua_io_done = TRUE; *size = io->lua_io_len; return io->lua_io_script; } } /* ** DKIMF_LUA_WRITER -- extract a compiled script from a Lua state ** ** Parameters: ** l -- Lua state ** buf -- buffer being written ** sz -- size of buffer ** data -- pointer to a Lua I/O structure ** ** Return value: ** 0 on success, !0 on error. */ static int dkimf_lua_writer(lua_State *l, const void *buf, size_t sz, void *data) { struct dkimf_lua_io *io; assert(l != NULL); assert(buf != NULL); assert(data != NULL); io = (struct dkimf_lua_io *) data; if (io->lua_io_alloc < io->lua_io_len + sz) { size_t newsz; size_t need; void *new; newsz = io->lua_io_alloc; need = io->lua_io_len + sz; while (newsz < need) newsz += BUFRSZ; if (io->lua_io_alloc == 0) new = malloc(newsz); else new = realloc((void *) io->lua_io_script, newsz); if (new == NULL) return -1; io->lua_io_script = new; io->lua_io_alloc = newsz; } memcpy((void *) (io->lua_io_script + io->lua_io_len), buf, sz); io->lua_io_len += sz; return 0; } /* ** DKIMF_LUA_ALLOC -- allocate memory ** ** Parameters: ** ud -- context (not used) ** ptr -- pointer (for realloc()) ** osize -- old size ** nsize -- new size ** ** Return value: ** Allocated memory, or NULL on failure. */ static void * dkimf_lua_alloc(void *ud, void *ptr, size_t osize, size_t nsize) { if (nsize == 0 && osize != 0) { free(ptr); return NULL; } # if LUA_VERSION_NUM == 502 else if (nsize != 0 && ptr == NULL) # else /* LUA_VERSION_NUM == 502 */ else if (nsize != 0 && osize == 0) # endif /* LUA_VERSION_NUM == 502 */ { return malloc(nsize); } else { return realloc(ptr, nsize); } } /* ** DKIMF_LUA_GC_ADD -- add an item for garbage collection ** ** Parameters: ** gc -- garbage collection handle ** item -- item to add ** type -- item type ** ** Return value: ** None. */ void dkimf_lua_gc_add(struct dkimf_lua_gc *gc, void *item, int type) { struct dkimf_lua_gc_item *new; assert(gc != NULL); assert(item != NULL); new = (struct dkimf_lua_gc_item *) malloc(sizeof *new); assert(new != NULL); new->gci_item = item; new->gci_type = type; new->gci_next = NULL; if (gc->gc_head == NULL) gc->gc_head = new; if (gc->gc_tail != NULL) gc->gc_tail->gci_next = new; gc->gc_tail = new; } /* ** DKIMF_LUA_GC_REMOVE -- remove an item from garbage collection ** ** Parameters: ** gc -- garbage collection handle ** item -- item to remove ** ** Return value: ** None. */ void dkimf_lua_gc_remove(struct dkimf_lua_gc *gc, void *item) { struct dkimf_lua_gc_item *cur; struct dkimf_lua_gc_item *prev = NULL; assert(gc != NULL); assert(item != NULL); cur = gc->gc_head; while (cur != NULL) { if (cur->gci_item == item) { if (cur == gc->gc_head) /* head */ { gc->gc_head = cur->gci_next; free(cur); cur = gc->gc_head; } else if (cur == gc->gc_tail) /* tail */ { prev->gci_next = NULL; gc->gc_tail = prev; free(cur); cur = NULL; } else /* middle */ { prev->gci_next = cur->gci_next; free(cur); cur = prev->gci_next; } } else { prev = cur; cur = cur->gci_next; } } } /* ** DKIMF_LUA_GC_CLEANUP -- perform garbage collection ** ** Parameters: ** gc -- garbage collection handle ** ** Return value: ** None. */ void dkimf_lua_gc_cleanup(struct dkimf_lua_gc *gc) { struct dkimf_lua_gc_item *cur; struct dkimf_lua_gc_item *next; assert(gc != NULL); cur = gc->gc_head; while (cur != NULL) { switch (cur->gci_type) { case DKIMF_LUA_GC_DB: (void) dkimf_db_close((DKIMF_DB) cur->gci_item); break; default: assert(0); } next = cur->gci_next; free(cur); cur = next; } } #ifdef DKIMF_LUA_CONTEXT_HOOKS /* ** DKIMF_LUA_SETUP_HOOK -- hook to Lua for handling a message during setup ** ** Parameters: ** ctx -- session context, for making calls back to opendkim.c ** script -- script to run ** scriptlen -- length of script; if 0, use strlen() ** name -- name of the script (for logging) ** lres -- Lua result structure ** keep -- where to save the script (or NULL) ** funclen -- size of the saved object ** ** Return value: ** 2 -- processing error ** 1 -- script contains a syntax error ** 0 -- success ** -1 -- memory allocation failure ** ** Side effects: ** lres may be modified to relay the script's signing requests, i.e. ** which key/selector(s) to use, whether to use "l=", etc. ** ** Notes: ** Called by mlfi_eoh() so it can decide what signature(s) to apply. */ int dkimf_lua_setup_hook(void *ctx, const char *script, size_t scriptlen, const char *name, struct dkimf_lua_script_result *lres, void **keep, size_t *funclen) { int status; lua_State *l = NULL; struct dkimf_lua_io io; struct dkimf_lua_gc gc; assert(script != NULL); assert(lres != NULL); io.lua_io_done = FALSE; io.lua_io_script = script; if (scriptlen == 0) io.lua_io_len = strlen(script); else io.lua_io_len = scriptlen; gc.gc_head = NULL; gc.gc_tail = NULL; l = lua_newstate(dkimf_lua_alloc, NULL); if (l == NULL) return -1; luaL_openlibs(l); /* ** Register functions. */ # if LUA_VERSION_NUM == 502 luaL_newlib(l, dkimf_lua_lib_setup); lua_setglobal(l, "odkim"); # else /* LUA_VERSION_NUM == 502 */ luaL_register(l, "odkim", dkimf_lua_lib_setup); # endif /* LUA_VERSION_NUM == 502 */ lua_pop(l, 1); /* ** Register constants. */ /* garbage collection handle */ lua_pushlightuserdata(l, &gc); lua_setglobal(l, DKIMF_GC); /* DB handle constants */ lua_pushnumber(l, DB_DOMAINS); lua_setglobal(l, "DB_DOMAINS"); lua_pushnumber(l, DB_THIRDPARTY); lua_setglobal(l, "DB_THIRDPARTY"); lua_pushnumber(l, DB_DONTSIGNTO); lua_setglobal(l, "DB_DONTSIGNTO"); lua_pushnumber(l, DB_MTAS); lua_setglobal(l, "DB_MTAS"); lua_pushnumber(l, DB_MACROS); lua_setglobal(l, "DB_MACROS"); lua_pushnumber(l, DB_SIGNINGTABLE); lua_setglobal(l, "DB_SIGNINGTABLE"); /* set result code */ lua_pushnumber(l, SMFIS_TEMPFAIL); lua_setglobal(l, "SMFIS_TEMPFAIL"); lua_pushnumber(l, SMFIS_ACCEPT); lua_setglobal(l, "SMFIS_ACCEPT"); lua_pushnumber(l, SMFIS_DISCARD); lua_setglobal(l, "SMFIS_DISCARD"); lua_pushnumber(l, SMFIS_REJECT); lua_setglobal(l, "SMFIS_REJECT"); /* filter context */ lua_pushlightuserdata(l, ctx); lua_setglobal(l, "ctx"); /* import other globals */ dkimf_import_globals(ctx, l); # if LUA_VERSION_NUM == 502 switch (lua_load(l, dkimf_lua_reader, (void *) &io, name, NULL)) # else /* LUA_VERSION_NUM == 502 */ switch (lua_load(l, dkimf_lua_reader, (void *) &io, name)) # endif /* LUA_VERSION_NUM == 502 */ { case 0: break; case LUA_ERRSYNTAX: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return 1; case LUA_ERRMEM: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return -1; default: assert(0); } if (keep != NULL && funclen != NULL) { io.lua_io_done = FALSE; io.lua_io_script = NULL; io.lua_io_len = 0; io.lua_io_alloc = 0; if (lua_dump(l, dkimf_lua_writer, &io) == 0) { *keep = (void *) io.lua_io_script; *funclen = io.lua_io_len; } } status = lua_pcall(l, 0, LUA_MULTRET, 0); if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); dkimf_lua_gc_cleanup(&gc); lua_close(l); return (status == 0 ? 0 : 2); } /* ** DKIMF_LUA_SCREEN_HOOK -- hook to Lua for handling a message after the ** verifying handle is established and all headers ** have been fed to it ** ** Parameters: ** ctx -- session context, for making calls back to opendkim.c ** script -- script to run ** scriptlen -- length of script; if 0, use strlen() ** name -- name of the script (for logging) ** lres -- Lua result structure ** keep -- where to save the script (or NULL) ** funclen -- size of the saved object ** ** Return value: ** 2 -- processing error ** 1 -- script contains a syntax error ** 0 -- success ** -1 -- memory allocation failure ** ** Notes: ** Called by mlfi_eom() so it can decide whether or not the message ** is acceptable. */ int dkimf_lua_screen_hook(void *ctx, const char *script, size_t scriptlen, const char *name, struct dkimf_lua_script_result *lres, void **keep, size_t *funclen) { int status; lua_State *l = NULL; struct dkimf_lua_io io; struct dkimf_lua_gc gc; assert(script != NULL); assert(lres != NULL); io.lua_io_done = FALSE; io.lua_io_script = script; if (scriptlen == 0) io.lua_io_len = strlen(script); else io.lua_io_len = scriptlen; gc.gc_head = NULL; gc.gc_tail = NULL; l = lua_newstate(dkimf_lua_alloc, NULL); if (l == NULL) return -1; luaL_openlibs(l); /* ** Register functions. */ # if LUA_VERSION_NUM == 502 luaL_newlib(l, dkimf_lua_lib_screen); lua_setglobal(l, "odkim"); # else /* LUA_VERSION_NUM == 502 */ luaL_register(l, "odkim", dkimf_lua_lib_screen); # endif /* LUA_VERSION_NUM == 502 */ lua_pop(l, 1); /* ** Register constants. */ /* garbage collection handle */ lua_pushlightuserdata(l, &gc); lua_setglobal(l, DKIMF_GC); /* DB handles */ lua_pushnumber(l, DB_DOMAINS); lua_setglobal(l, "DB_DOMAINS"); lua_pushnumber(l, DB_THIRDPARTY); lua_setglobal(l, "DB_THIRDPARTY"); lua_pushnumber(l, DB_DONTSIGNTO); lua_setglobal(l, "DB_DONTSIGNTO"); lua_pushnumber(l, DB_MTAS); lua_setglobal(l, "DB_MTAS"); lua_pushnumber(l, DB_MACROS); lua_setglobal(l, "DB_MACROS"); lua_pushnumber(l, DB_SIGNINGTABLE); lua_setglobal(l, "DB_SIGNINGTABLE"); /* milter context */ lua_pushlightuserdata(l, ctx); lua_setglobal(l, "ctx"); /* import other globals */ dkimf_import_globals(ctx, l); # if LUA_VERSION_NUM == 502 switch (lua_load(l, dkimf_lua_reader, (void *) &io, name, NULL)) # else /* LUA_VERSION_NUM == 502 */ switch (lua_load(l, dkimf_lua_reader, (void *) &io, name)) # endif /* LUA_VERSION_NUM == 502 */ { case 0: break; case LUA_ERRSYNTAX: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return 1; case LUA_ERRMEM: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return -1; default: assert(0); } if (keep != NULL && funclen != NULL) { io.lua_io_done = FALSE; io.lua_io_script = NULL; io.lua_io_len = 0; io.lua_io_alloc = 0; if (lua_dump(l, dkimf_lua_writer, &io) == 0) { *keep = (void *) io.lua_io_script; *funclen = io.lua_io_len; } } status = lua_pcall(l, 0, LUA_MULTRET, 0); if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); dkimf_lua_gc_cleanup(&gc); lua_close(l); return (status == 0 ? 0 : 2); } # ifdef _FFR_STATSEXT /* ** DKIMF_LUA_STATS_HOOK -- hook to Lua for recording statistics after ** verifying has been done ** ** Parameters: ** ctx -- session context, for making calls back to opendkim.c ** script -- script to run ** scriptlen -- length of script; if 0, use strlen() ** name -- name of the script (for logging) ** lres -- Lua result structure ** keep -- where to save the script (or NULL) ** funclen -- size of the saved object ** ** Return value: ** 2 -- processing error ** 1 -- script contains a syntax error ** 0 -- success ** -1 -- memory allocation failure ** ** Notes: ** Called by mlfi_eom() so it can pass extra statistical parameters ** to the stats recording module. */ int dkimf_lua_stats_hook(void *ctx, const char *script, size_t scriptlen, const char *name, struct dkimf_lua_script_result *lres, void **keep, size_t *funclen) { int status; lua_State *l = NULL; struct dkimf_lua_io io; struct dkimf_lua_gc gc; assert(script != NULL); assert(lres != NULL); io.lua_io_done = FALSE; io.lua_io_script = script; if (scriptlen == 0) io.lua_io_len = strlen(script); else io.lua_io_len = scriptlen; gc.gc_head = NULL; gc.gc_tail = NULL; l = lua_newstate(dkimf_lua_alloc, NULL); if (l == NULL) return -1; luaL_openlibs(l); /* ** Register functions. */ # if LUA_VERSION_NUM == 502 luaL_newlib(l, dkimf_lua_lib_stats); lua_setglobal(l, "odkim"); # else /* LUA_VERSION_NUM == 502 */ luaL_register(l, "odkim", dkimf_lua_lib_stats); # endif /* LUA_VERSION_NUM == 502 */ lua_pop(l, 1); /* ** Register constants. */ /* garbage collection handle */ lua_pushlightuserdata(l, &gc); lua_setglobal(l, DKIMF_GC); /* milter result codes */ lua_pushnumber(l, SMFIS_TEMPFAIL); lua_setglobal(l, "SMFIS_TEMPFAIL"); lua_pushnumber(l, SMFIS_ACCEPT); lua_setglobal(l, "SMFIS_ACCEPT"); lua_pushnumber(l, SMFIS_DISCARD); lua_setglobal(l, "SMFIS_DISCARD"); lua_pushnumber(l, SMFIS_REJECT); lua_setglobal(l, "SMFIS_REJECT"); /* signature "bh" result codes */ lua_pushnumber(l, DKIM_SIGBH_UNTESTED); lua_setglobal(l, "DKIM_SIGBH_UNTESTED"); lua_pushnumber(l, DKIM_SIGBH_MATCH); lua_setglobal(l, "DKIM_SIGBH_MATCH"); lua_pushnumber(l, DKIM_SIGBH_MISMATCH); lua_setglobal(l, "DKIM_SIGBH_MISMATCH"); /* signature error codes */ lua_pushnumber(l, DKIM_SIGERROR_UNKNOWN); lua_setglobal(l, "DKIM_SIGERROR_UNKNOWN"); lua_pushnumber(l, DKIM_SIGERROR_OK); lua_setglobal(l, "DKIM_SIGERROR_OK"); lua_pushnumber(l, DKIM_SIGERROR_VERSION); lua_setglobal(l, "DKIM_SIGERROR_VERSION"); lua_pushnumber(l, DKIM_SIGERROR_DOMAIN); lua_setglobal(l, "DKIM_SIGERROR_DOMAIN"); lua_pushnumber(l, DKIM_SIGERROR_EXPIRED); lua_setglobal(l, "DKIM_SIGERROR_EXPIRED"); lua_pushnumber(l, DKIM_SIGERROR_FUTURE); lua_setglobal(l, "DKIM_SIGERROR_FUTURE"); lua_pushnumber(l, DKIM_SIGERROR_TIMESTAMPS); lua_setglobal(l, "DKIM_SIGERROR_TIMESTAMPS"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_HC); lua_setglobal(l, "DKIM_SIGERROR_INVALID_HC"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_BC); lua_setglobal(l, "DKIM_SIGERROR_INVALID_BC"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_A); lua_setglobal(l, "DKIM_SIGERROR_MISSING_A"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_A); lua_setglobal(l, "DKIM_SIGERROR_INVALID_A"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_H); lua_setglobal(l, "DKIM_SIGERROR_MISSING_H"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_L); lua_setglobal(l, "DKIM_SIGERROR_INVALID_L"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_Q); lua_setglobal(l, "DKIM_SIGERROR_INVALID_Q"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_QO); lua_setglobal(l, "DKIM_SIGERROR_INVALID_QO"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_D); lua_setglobal(l, "DKIM_SIGERROR_MISSING_D"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_D); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_D"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_S); lua_setglobal(l, "DKIM_SIGERROR_MISSING_S"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_S); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_S"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_B); lua_setglobal(l, "DKIM_SIGERROR_MISSING_B"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_B); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_B"); lua_pushnumber(l, DKIM_SIGERROR_CORRUPT_B); lua_setglobal(l, "DKIM_SIGERROR_CORRUPT_B"); lua_pushnumber(l, DKIM_SIGERROR_NOKEY); lua_setglobal(l, "DKIM_SIGERROR_NOKEY"); lua_pushnumber(l, DKIM_SIGERROR_DNSSYNTAX); lua_setglobal(l, "DKIM_SIGERROR_DNSSYNTAX"); lua_pushnumber(l, DKIM_SIGERROR_KEYFAIL); lua_setglobal(l, "DKIM_SIGERROR_KEYFAIL"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_BH); lua_setglobal(l, "DKIM_SIGERROR_MISSING_BH"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_BH); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_BH"); lua_pushnumber(l, DKIM_SIGERROR_CORRUPT_BH); lua_setglobal(l, "DKIM_SIGERROR_CORRUPT_BH"); lua_pushnumber(l, DKIM_SIGERROR_BADSIG); lua_setglobal(l, "DKIM_SIGERROR_BADSIG"); lua_pushnumber(l, DKIM_SIGERROR_SUBDOMAIN); lua_setglobal(l, "DKIM_SIGERROR_SUBDOMAIN"); lua_pushnumber(l, DKIM_SIGERROR_MULTIREPLY); lua_setglobal(l, "DKIM_SIGERROR_MULTIREPLY"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_H); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_H"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_H); lua_setglobal(l, "DKIM_SIGERROR_INVALID_H"); lua_pushnumber(l, DKIM_SIGERROR_TOOLARGE_L); lua_setglobal(l, "DKIM_SIGERROR_TOOLARGE_L"); lua_pushnumber(l, DKIM_SIGERROR_MBSFAILED); lua_setglobal(l, "DKIM_SIGERROR_MBSFAILED"); lua_pushnumber(l, DKIM_SIGERROR_KEYVERSION); lua_setglobal(l, "DKIM_SIGERROR_KEYVERSION"); lua_pushnumber(l, DKIM_SIGERROR_KEYUNKNOWNHASH); lua_setglobal(l, "DKIM_SIGERROR_KEYUNKNOWNHASH"); lua_pushnumber(l, DKIM_SIGERROR_KEYHASHMISMATCH); lua_setglobal(l, "DKIM_SIGERROR_KEYHASHMISMATCH"); lua_pushnumber(l, DKIM_SIGERROR_NOTEMAILKEY); lua_setglobal(l, "DKIM_SIGERROR_NOTEMAILKEY"); lua_pushnumber(l, DKIM_SIGERROR_KEYTYPEMISSING); lua_setglobal(l, "DKIM_SIGERROR_KEYTYPEMISSING"); lua_pushnumber(l, DKIM_SIGERROR_KEYTYPEUNKNOWN); lua_setglobal(l, "DKIM_SIGERROR_KEYTYPEUNKNOWN"); lua_pushnumber(l, DKIM_SIGERROR_KEYREVOKED); lua_setglobal(l, "DKIM_SIGERROR_KEYREVOKED"); lua_pushnumber(l, DKIM_SIGERROR_KEYDECODE); lua_setglobal(l, "DKIM_SIGERROR_KEYDECODE"); /* milter context */ lua_pushlightuserdata(l, ctx); lua_setglobal(l, "ctx"); /* import other globals */ dkimf_import_globals(ctx, l); # if LUA_VERSION_NUM == 502 switch (lua_load(l, dkimf_lua_reader, (void *) &io, name, NULL)) # else /* LUA_VERSION_NUM == 502 */ switch (lua_load(l, dkimf_lua_reader, (void *) &io, name)) # endif /* LUA_VERSION_NUM == 502 */ { case 0: break; case LUA_ERRSYNTAX: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return 1; case LUA_ERRMEM: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return -1; default: assert(0); } if (keep != NULL && funclen != NULL) { io.lua_io_done = FALSE; io.lua_io_script = NULL; io.lua_io_len = 0; io.lua_io_alloc = 0; if (lua_dump(l, dkimf_lua_writer, &io) == 0) { *keep = (void *) io.lua_io_script; *funclen = io.lua_io_len; } } status = lua_pcall(l, 0, LUA_MULTRET, 0); if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); dkimf_lua_gc_cleanup(&gc); lua_close(l); return (status == 0 ? 0 : 2); } # endif /* _FFR_STATSEXT */ /* ** DKIMF_LUA_FINAL_HOOK -- hook to Lua for handling a message after all ** signing and verifying has been done ** ** Parameters: ** ctx -- session context, for making calls back to opendkim.c ** script -- script to run ** scriptlen -- length of script; if 0, use strlen() ** name -- name of the script (for logging) ** lres -- Lua result structure ** keep -- where to save the script (or NULL) ** funclen -- size of the saved object ** ** Return value: ** 2 -- processing error ** 1 -- script contains a syntax error ** 0 -- success ** -1 -- memory allocation failure ** ** Notes: ** Called by mlfi_eom() so it can decide whether or not the message ** is acceptable. */ int dkimf_lua_final_hook(void *ctx, const char *script, size_t scriptlen, const char *name, struct dkimf_lua_script_result *lres, void **keep, size_t *funclen) { int status; lua_State *l = NULL; struct dkimf_lua_io io; struct dkimf_lua_gc gc; assert(script != NULL); assert(lres != NULL); io.lua_io_done = FALSE; io.lua_io_script = script; if (scriptlen == 0) io.lua_io_len = strlen(script); else io.lua_io_len = scriptlen; gc.gc_head = NULL; gc.gc_tail = NULL; l = lua_newstate(dkimf_lua_alloc, NULL); if (l == NULL) return -1; luaL_openlibs(l); /* ** Register functions. */ # if LUA_VERSION_NUM == 502 luaL_newlib(l, dkimf_lua_lib_final); lua_setglobal(l, "odkim"); # else /* LUA_VERSION_NUM == 502 */ luaL_register(l, "odkim", dkimf_lua_lib_final); # endif /* LUA_VERSION_NUM == 502 */ lua_pop(l, 1); /* ** Register constants. */ /* garbage collection handle */ lua_pushlightuserdata(l, &gc); lua_setglobal(l, DKIMF_GC); /* milter result codes */ lua_pushnumber(l, SMFIS_TEMPFAIL); lua_setglobal(l, "SMFIS_TEMPFAIL"); lua_pushnumber(l, SMFIS_ACCEPT); lua_setglobal(l, "SMFIS_ACCEPT"); lua_pushnumber(l, SMFIS_DISCARD); lua_setglobal(l, "SMFIS_DISCARD"); lua_pushnumber(l, SMFIS_REJECT); lua_setglobal(l, "SMFIS_REJECT"); /* signature "bh" result codes */ lua_pushnumber(l, DKIM_SIGBH_UNTESTED); lua_setglobal(l, "DKIM_SIGBH_UNTESTED"); lua_pushnumber(l, DKIM_SIGBH_MATCH); lua_setglobal(l, "DKIM_SIGBH_MATCH"); lua_pushnumber(l, DKIM_SIGBH_MISMATCH); lua_setglobal(l, "DKIM_SIGBH_MISMATCH"); /* signature error codes */ lua_pushnumber(l, DKIM_SIGERROR_UNKNOWN); lua_setglobal(l, "DKIM_SIGERROR_UNKNOWN"); lua_pushnumber(l, DKIM_SIGERROR_OK); lua_setglobal(l, "DKIM_SIGERROR_OK"); lua_pushnumber(l, DKIM_SIGERROR_VERSION); lua_setglobal(l, "DKIM_SIGERROR_VERSION"); lua_pushnumber(l, DKIM_SIGERROR_DOMAIN); lua_setglobal(l, "DKIM_SIGERROR_DOMAIN"); lua_pushnumber(l, DKIM_SIGERROR_EXPIRED); lua_setglobal(l, "DKIM_SIGERROR_EXPIRED"); lua_pushnumber(l, DKIM_SIGERROR_FUTURE); lua_setglobal(l, "DKIM_SIGERROR_FUTURE"); lua_pushnumber(l, DKIM_SIGERROR_TIMESTAMPS); lua_setglobal(l, "DKIM_SIGERROR_TIMESTAMPS"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_HC); lua_setglobal(l, "DKIM_SIGERROR_INVALID_HC"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_BC); lua_setglobal(l, "DKIM_SIGERROR_INVALID_BC"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_A); lua_setglobal(l, "DKIM_SIGERROR_MISSING_A"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_A); lua_setglobal(l, "DKIM_SIGERROR_INVALID_A"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_H); lua_setglobal(l, "DKIM_SIGERROR_MISSING_H"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_L); lua_setglobal(l, "DKIM_SIGERROR_INVALID_L"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_Q); lua_setglobal(l, "DKIM_SIGERROR_INVALID_Q"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_QO); lua_setglobal(l, "DKIM_SIGERROR_INVALID_QO"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_D); lua_setglobal(l, "DKIM_SIGERROR_MISSING_D"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_D); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_D"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_S); lua_setglobal(l, "DKIM_SIGERROR_MISSING_S"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_S); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_S"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_B); lua_setglobal(l, "DKIM_SIGERROR_MISSING_B"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_B); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_B"); lua_pushnumber(l, DKIM_SIGERROR_CORRUPT_B); lua_setglobal(l, "DKIM_SIGERROR_CORRUPT_B"); lua_pushnumber(l, DKIM_SIGERROR_NOKEY); lua_setglobal(l, "DKIM_SIGERROR_NOKEY"); lua_pushnumber(l, DKIM_SIGERROR_DNSSYNTAX); lua_setglobal(l, "DKIM_SIGERROR_DNSSYNTAX"); lua_pushnumber(l, DKIM_SIGERROR_KEYFAIL); lua_setglobal(l, "DKIM_SIGERROR_KEYFAIL"); lua_pushnumber(l, DKIM_SIGERROR_MISSING_BH); lua_setglobal(l, "DKIM_SIGERROR_MISSING_BH"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_BH); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_BH"); lua_pushnumber(l, DKIM_SIGERROR_CORRUPT_BH); lua_setglobal(l, "DKIM_SIGERROR_CORRUPT_BH"); lua_pushnumber(l, DKIM_SIGERROR_BADSIG); lua_setglobal(l, "DKIM_SIGERROR_BADSIG"); lua_pushnumber(l, DKIM_SIGERROR_SUBDOMAIN); lua_setglobal(l, "DKIM_SIGERROR_SUBDOMAIN"); lua_pushnumber(l, DKIM_SIGERROR_MULTIREPLY); lua_setglobal(l, "DKIM_SIGERROR_MULTIREPLY"); lua_pushnumber(l, DKIM_SIGERROR_EMPTY_H); lua_setglobal(l, "DKIM_SIGERROR_EMPTY_H"); lua_pushnumber(l, DKIM_SIGERROR_INVALID_H); lua_setglobal(l, "DKIM_SIGERROR_INVALID_H"); lua_pushnumber(l, DKIM_SIGERROR_TOOLARGE_L); lua_setglobal(l, "DKIM_SIGERROR_TOOLARGE_L"); lua_pushnumber(l, DKIM_SIGERROR_MBSFAILED); lua_setglobal(l, "DKIM_SIGERROR_MBSFAILED"); lua_pushnumber(l, DKIM_SIGERROR_KEYVERSION); lua_setglobal(l, "DKIM_SIGERROR_KEYVERSION"); lua_pushnumber(l, DKIM_SIGERROR_KEYUNKNOWNHASH); lua_setglobal(l, "DKIM_SIGERROR_KEYUNKNOWNHASH"); lua_pushnumber(l, DKIM_SIGERROR_KEYHASHMISMATCH); lua_setglobal(l, "DKIM_SIGERROR_KEYHASHMISMATCH"); lua_pushnumber(l, DKIM_SIGERROR_NOTEMAILKEY); lua_setglobal(l, "DKIM_SIGERROR_NOTEMAILKEY"); lua_pushnumber(l, DKIM_SIGERROR_KEYTYPEMISSING); lua_setglobal(l, "DKIM_SIGERROR_KEYTYPEMISSING"); lua_pushnumber(l, DKIM_SIGERROR_KEYTYPEUNKNOWN); lua_setglobal(l, "DKIM_SIGERROR_KEYTYPEUNKNOWN"); lua_pushnumber(l, DKIM_SIGERROR_KEYREVOKED); lua_setglobal(l, "DKIM_SIGERROR_KEYREVOKED"); lua_pushnumber(l, DKIM_SIGERROR_KEYDECODE); lua_setglobal(l, "DKIM_SIGERROR_KEYDECODE"); /* milter context */ lua_pushlightuserdata(l, ctx); lua_setglobal(l, "ctx"); /* import other globals */ dkimf_import_globals(ctx, l); # if LUA_VERSION_NUM == 502 switch (lua_load(l, dkimf_lua_reader, (void *) &io, name, NULL)) # else /* LUA_VERSION_NUM == 502 */ switch (lua_load(l, dkimf_lua_reader, (void *) &io, name)) # endif /* LUA_VERSION_NUM == 502 */ { case 0: break; case LUA_ERRSYNTAX: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return 1; case LUA_ERRMEM: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return -1; default: assert(0); } if (keep != NULL && funclen != NULL) { io.lua_io_done = FALSE; io.lua_io_script = NULL; io.lua_io_len = 0; io.lua_io_alloc = 0; if (lua_dump(l, dkimf_lua_writer, &io) == 0) { *keep = (void *) io.lua_io_script; *funclen = io.lua_io_len; } } status = lua_pcall(l, 0, LUA_MULTRET, 0); if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); dkimf_lua_gc_cleanup(&gc); lua_close(l); return (status == 0 ? 0 : 2); } #endif /* DKIMF_LUA_CONTEXT_HOOKS */ /* ** DKIMF_LUA_DB_HOOK -- hook to Lua for handling a DB query ** ** Parameters: ** script -- script to run ** scriptlen -- length of script; if 0, use strlen() ** query -- query string ** lres -- Lua result structure ** keep -- where to save the script (or NULL) ** funclen -- size of the saved object ** ** Return value: ** 2 -- processing error ** 1 -- script contains a syntax error ** 0 -- success ** -1 -- memory allocation failure */ int dkimf_lua_db_hook(const char *script, size_t scriptlen, const char *query, struct dkimf_lua_script_result *lres, void **keep, size_t *funclen) { int status; struct dkimf_lua_io io; lua_State *l = NULL; assert(script != NULL); assert(lres != NULL); io.lua_io_done = FALSE; io.lua_io_script = script; if (scriptlen == 0) io.lua_io_len = strlen(script); else io.lua_io_len = scriptlen; l = lua_newstate(dkimf_lua_alloc, NULL); if (l == NULL) return -1; luaL_openlibs(l); /* query string */ if (query == NULL) lua_pushnil(l); else lua_pushstring(l, query); lua_setglobal(l, "query"); # if LUA_VERSION_NUM == 502 switch (lua_load(l, dkimf_lua_reader, (void *) &io, script, NULL)) # else /* LUA_VERSION_NUM == 502 */ switch (lua_load(l, dkimf_lua_reader, (void *) &io, script)) # endif /* LUA_VERSION_NUM == 502 */ { case 0: break; case LUA_ERRSYNTAX: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return 1; case LUA_ERRMEM: if (lua_isstring(l, 1)) lres->lrs_error = strdup(lua_tostring(l, 1)); lua_close(l); return -1; default: assert(0); } if (keep != NULL && funclen != NULL) { io.lua_io_done = FALSE; io.lua_io_script = NULL; io.lua_io_len = 0; io.lua_io_alloc = 0; if (lua_dump(l, dkimf_lua_writer, &io) == 0) { *keep = (void *) io.lua_io_script; *funclen = io.lua_io_len; } } status = lua_pcall(l, 0, LUA_MULTRET, 0); if (status != 0 && lua_isstring(l, 1)) { lres->lrs_error = strdup(lua_tostring(l, 1)); lres->lrs_rcount = 0; } else if (status == 0) { size_t asz; lres->lrs_rcount = lua_gettop(l); asz = sizeof(char *) * lres->lrs_rcount; lres->lrs_results = (char **) malloc(asz); if (lres->lrs_results != NULL) { int c; for (c = 0; c < lres->lrs_rcount; c++) { lres->lrs_results[c] = strdup(lua_tostring(l, c + 1)); } } } lua_close(l); return (status == 0 ? 0 : 2); } #endif /* USE_LUA */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-lua.h000066400000000000000000000040131337314105200230170ustar00rootroot00000000000000/* ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. ** */ #ifndef _OPENDKIM_LUA_H_ #define _OPENDKIM_LUA_H_ /* system includes */ #include /* types */ struct dkimf_lua_script_result { int lrs_rcount; char * lrs_error; char ** lrs_results; }; struct dkimf_lua_gc_item { int gci_type; void * gci_item; struct dkimf_lua_gc_item * gci_next; }; struct dkimf_lua_gc { struct dkimf_lua_gc_item * gc_head; struct dkimf_lua_gc_item * gc_tail; }; /* macros */ #define DKIMF_GC "_DKIMF_GC" #define DKIMF_LUA_GC_DB 1 /* prototypes */ extern int dkimf_lua_db_hook __P((const char *, size_t, const char *, struct dkimf_lua_script_result *, void **, size_t *)); extern int dkimf_lua_final_hook __P((void *, const char *, size_t, const char *, struct dkimf_lua_script_result *, void **, size_t *)); extern void dkimf_lua_gc_add __P((struct dkimf_lua_gc *g, void *, int)); extern void dkimf_lua_gc_cleanup __P((struct dkimf_lua_gc *)); extern void dkimf_lua_gc_remove __P((struct dkimf_lua_gc *, void *)); extern int dkimf_lua_screen_hook __P((void *, const char *, size_t, const char *, struct dkimf_lua_script_result *, void **, size_t *)); extern int dkimf_lua_setup_hook __P((void *, const char *, size_t, const char *, struct dkimf_lua_script_result *, void **, size_t *)); #ifdef _FFR_STATSEXT extern int dkimf_lua_stats_hook __P((void *, const char *, size_t, const char *, struct dkimf_lua_script_result *, void **, size_t *)); #endif /* _FFR_STATSEXT */ #endif /* _OPENDKIM_LUA_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-spam.1.in000066400000000000000000000105301337314105200235150ustar00rootroot00000000000000.TH opendkim-spam 1 "The Trusted Domain Project" .SH NAME .B opendkim-spam \- DKIM filter spam correlation tool .SH SYNOPSIS .B opendkim-spam [options] .SH DESCRIPTION .B opendkim-spam accepts a regular format message (RFC5322) on standard input and uses it to update a local SQL database being updated by .I opendkim(8) with an indiciation that a user believes the input message is spam or otherwise abusive. This feedback is important input toward developing DKIM-based domain reputation systems. The tool is intended to be used directly from within shell-based mail readers such as .I alpine(1) or .I mutt(1) using a "pipe" command, which feeds the message being read to the specified program. This tool is experimental. If the experiment proves useful, the feedback could be used as an input stream to a larger-scale collaborative feedback system that can be used to identify sources of signed mail that have good reputations. .SH OPTIONS .TP .I -b backend Specifies the style of backend database in use. The default is "@SQL_BACKEND@". .TP .I -c file Names a configuration file from which operating parameters will be read. The configuration file contains entries of the form "key value", one per line. Empty lines or lines beginning with a hash ("#") character are ignored. Command line equivalents for the configuration file are available as runtime overrides. The default configuration file location is .I @SYSCONFDIR@/opendkim-spam.conf. See the CONFIGURATION FILE section for a list of known values. .TP .I -f Run in the foreground rather than executing as a background process. Intended mainly for debugging. .TP .I -d name Indicates the name of the database to be accessed. The default is "opendkim". .TP .I -h host Specifies the host where the database server is running. The default is "localhost". .TP .I -o file Writes an update record to an OpenDKIM statistics file rather than directly to a database. There is no default. Note that if this option is used, all database-specific options are ignored. .TP .I -p password Specifies the password to be used when authenticating to the database. The default is "opendkim". .TP .I -P port Specifies the port number where the database server is listening. The default depends on which backend is in use. .TP .I -r reporter Provides the name of the site reporting the spam. If not provided, an attempt will be made to extract this information from the topmost Received header field from the input message. .TP .I -s column Names the database column whose value should be incremented as a result of this user action. The default is "spam". .TP .I -u user Identifies the database user to be used when connecting to the database. The default is "opendkim". .TP .I -v Requests verbose output. Can be specified multiple times for more and more information. .TP .I -V Print version number and exit. .SH CONFIGURATION FILE The configuration file used by .B opendkim-spam(1) is expected to be a text file. Empty lines or lines starting with a hash ("#") character are ignored. All other lines should consist of a parameter name followed by one or more whitespace characters, then followed by its intended value. Parameters generally match command line options (specified above), but when present the command line options override the configuration file options. The list of configuration file parameters and their command line equivalents are as follows; see above for descriptions: .TP .I Background \-f (opposite meaning) .TP .I DatabaseBackend \-b .TP .I DatabaseName \-d .TP .I DatabaseHost \-h .TP .I DatabasePassword \-p .TP .I DatabasePort \-P .TP .I DatabaseSpamColumn \-s .TP .I DatabaseUser \-u .TP .I ReporterID \-r .TP .I SkipReceived An integer that defines a number of Received fields that should be skipped while searching for the one that was also seen by .B opendkim(8) so that this command refers to the same Received field. Defaults to 0. .TP .I StatisticsFile \-o .SH NOTES It is possible to compile this application without SQL support, in which case only the .I StatisticsFile setting has any meaning (and, in fact, it is required in that case). .SH VERSION This man page covers the version of .I opendkim-spam that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I alpine(1), .I mutt(1), .I opendkim(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-spam.c000066400000000000000000000411361337314105200232000ustar00rootroot00000000000000/* ** Copyright (c) 2011-2013, 2015, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #ifdef USE_ODBX /* opendbx includes */ # include #endif /* USE_ODBX */ /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "config.h" #include "stats.h" /* definitions, macros, etc. */ #define BUFRSZ 1024 #define CMDLINEOPTS "b:c:d:fh:o:p:P:r:s:u:vV" #define DEFDBBACKEND SQL_BACKEND #undef DEFCONFFILE #define DEFCONFFILE CONFIG_BASE "/opendkim-spam.conf" #define DEFDBHOST "localhost" #define DEFDBNAME "opendkim" #define DEFDBPASS "opendkim" #define DEFDBPORT "" #define DEFDBSPAMCOL "spam" #define DEFDBUSER "opendkim" #define MAXHEADER 16384 #define SPACES "\r\n\t " #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* globals */ char *progname; /* config definition */ struct configdef spam_config[] = { { "Background", CONFIG_TYPE_BOOLEAN, FALSE }, { "DatabaseBackend", CONFIG_TYPE_STRING, FALSE }, { "DatabaseHost", CONFIG_TYPE_STRING, FALSE }, { "DatabaseName", CONFIG_TYPE_STRING, FALSE }, { "DatabasePassword", CONFIG_TYPE_STRING, FALSE }, { "DatabaseSpamColumn", CONFIG_TYPE_STRING, FALSE }, { "DatabaseUser", CONFIG_TYPE_STRING, FALSE }, { "ReporterID", CONFIG_TYPE_STRING, FALSE }, { "SkipReceived", CONFIG_TYPE_INTEGER, FALSE }, { "StatisticsFile", CONFIG_TYPE_STRING, FALSE }, { NULL, (u_int) -1, FALSE } }; /* ** USAGE -- usage message ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\n" "\t-b backend \tdatabase backend [%s]\n" "\t-c file \tconfiguration file [%s]\n" "\t-d dbname \tdatabase name [%s]\n" "\t-f \trun in the foreground\n" "\t-h dbhost \tdatabase hostname [%s]\n" "\t-o file \tstatistics file\n" "\t-p dbpass \tdatabase password [%s]\n" "\t-P dbport \tdatabase port [%s]\n" "\t-s dbspamcol\tdatabase spam column name [%s]\n" "\t-u dbuser \tdatabase user [%s]\n" "\t-r reporter \treporter id (reporting host name)\n" "\t-v \tbe more verbose\n" "\t-V \tprint version number and exit\n", progname, progname, DEFDBBACKEND, DEFCONFFILE, DEFDBNAME, DEFDBHOST, DEFDBPASS, DEFDBPORT, DEFDBSPAMCOL, DEFDBUSER); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { _Bool dofork = TRUE; int c; int verbose = 0; int dberr; int repid; int msgid; u_int skipcount = 0; char *p; char *prev; char *dbbackend = NULL; char *dbuser = NULL; char *dbpass = NULL; char *dbname = NULL; char *dbhost = NULL; char *dbspamcol = NULL; char *dbport = NULL; char *conffile = DEFCONFFILE; char *job = NULL; char *reporter = NULL; char *statsfile = NULL; FILE *sf; struct config *conf = NULL; #ifdef USE_ODBX odbx_t *db = NULL; odbx_result_t *result; #endif /* USE_ODBX */ char buf[BUFRSZ + 1]; char rcvd[MAXHEADER + 1]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) { switch (c) { case 'b': dbbackend = optarg; break; case 'c': conffile = optarg; break; case 'd': dbname = optarg; break; case 'f': dofork = FALSE; break; case 'h': dbhost = optarg; break; case 'P': dbport = optarg; break; case 'o': statsfile = optarg; break; case 'p': dbpass = optarg; break; case 's': dbspamcol = optarg; break; case 'u': dbuser = optarg; break; case 'r': reporter = optarg; break; case 'v': verbose++; break; case 'V': fprintf(stdout, "%s v%s\n", progname, VERSION); return EX_OK; default: return usage(); } } /* load from config file, if specified */ if (conffile != NULL) { _Bool tmpf; unsigned int line; char path[MAXPATHLEN + 1]; if (verbose >= 2) { fprintf(stdout, "%s: loading configuration from %s\n", progname, conffile); } memset(path, '\0', sizeof path); conf = config_load(conffile, spam_config, &line, path, sizeof path, NULL); if (conf == NULL) { fprintf(stderr, "%s: %s: configuration error at line %u: %s\n", progname, path, line, config_error()); return EX_CONFIG; } /* extract values */ (void) config_get(conf, "SkipReceived", &skipcount, sizeof skipcount); if (dbbackend == NULL) { (void) config_get(conf, "DatabaseBackend", &dbbackend, sizeof dbbackend); } if (dbhost == NULL) { (void) config_get(conf, "DatabaseHost", &dbhost, sizeof dbhost); } if (dbname == NULL) { (void) config_get(conf, "DatabaseName", &dbname, sizeof dbname); } if (dbpass == NULL) { (void) config_get(conf, "DatabasePassword", &dbpass, sizeof dbpass); } if (dbport == NULL) { (void) config_get(conf, "DatabasePort", &dbport, sizeof dbport); } if (dbspamcol == NULL) { (void) config_get(conf, "DatabaseSpamColumn", &dbspamcol, sizeof dbspamcol); } if (dbuser == NULL) { (void) config_get(conf, "DatabaseUser", &dbuser, sizeof dbuser); } if (reporter == NULL) { (void) config_get(conf, "ReporterID", &reporter, sizeof reporter); } if (statsfile == NULL) { (void) config_get(conf, "StatisticsFile", &statsfile, sizeof statsfile); } if (config_get(conf, "Background", &tmpf, sizeof tmpf) == 1) { if (dofork && !tmpf) tmpf = FALSE; } } if (dbbackend == NULL) dbbackend = DEFDBBACKEND; if (dbhost == NULL) dbhost = DEFDBHOST; if (dbname == NULL) dbname = DEFDBNAME; if (dbpass == NULL) dbpass = DEFDBPASS; if (dbspamcol == NULL) dbspamcol = DEFDBSPAMCOL; if (dbuser == NULL) dbuser = DEFDBUSER; /* connect to the DB */ if (statsfile != NULL) { sf = fopen(statsfile, "a"); if (sf == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, statsfile, strerror(errno)); return EX_OSERR; } /* write version if file is new */ if (ftell(sf) == 0) fprintf(sf, "V%d\n", DKIMS_VERSION); } else { #ifndef USE_ODBX fprintf(stderr, "%s: SQL not supported in this installation\n", progname); return EX_SOFTWARE; #else /* ! USE_ODBX */ dberr = odbx_init(&db, dbbackend, dbhost, dbport); if (dberr < 0) { fprintf(stderr, "%s: odbx_init(): %s\n", progname, odbx_error(NULL, dberr)); return EX_SOFTWARE; } if (verbose >= 1) { fprintf(stdout, "%s: connected to database on %s\n", progname, dbhost); } dberr = odbx_bind(db, dbname, dbuser, dbpass, ODBX_BIND_SIMPLE); if (dberr < 0) { fprintf(stderr, "%s: odbx_bind(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_finish(db); return EX_SOFTWARE; } if (verbose >= 2) { fprintf(stdout, "%s: database binding successful\n", progname); } #endif /* ! USE_ODBX */ } /* read first Received:, extract reporter and job ID */ memset(buf, '\0', sizeof buf); memset(rcvd, '\0', sizeof rcvd); while (fgets(buf, sizeof buf - 1, stdin) != NULL) { for (p = buf; *p != '\0'; p++) { if (*p == '\r' || *p == '\n') { *p = '\0'; break; } } if (strncasecmp(buf, "Received:", 9) == 0) { if (skipcount > 0) { skipcount--; continue; } else { strlcpy(rcvd, buf, sizeof rcvd); } } else if (isascii(buf[0]) && isspace(buf[0]) && rcvd[0] != '\0') { strlcat(rcvd, buf, sizeof rcvd); } else if (isascii(buf[0]) && !isspace(buf[0]) && rcvd[0] != '\0') { break; } } if (rcvd[0] == '\0') { fprintf(stderr, "%s: Received header field not found\n", progname); #ifdef USE_ODBX if (db != NULL) { (void) odbx_unbind(db); (void) odbx_finish(db); } else { #endif /* USE_ODBX */ fclose(sf); #ifdef USE_ODBX } #endif /* USE_ODBX */ return EX_DATAERR; } /* ** This is overly simplistic as it doesn't account for CFWS or ** escapes, but for now it's a good starting point. */ prev = NULL; for (p = strtok(&rcvd[9], SPACES); p != NULL; p = strtok(NULL, SPACES)) { if (prev != NULL) { if (strcasecmp(prev, "id") == 0) job = p; else if (reporter == NULL && strcasecmp(prev, "by") == 0) reporter = p; } prev = p; } if (job == NULL) { fprintf(stderr, "%s: could not locate job ID in Received header field\n", progname); #ifdef USE_ODBX if (db != NULL) { (void) odbx_unbind(db); (void) odbx_finish(db); } else { #endif /* USE_ODBX */ fclose(sf); #ifdef USE_ODBX } #endif /* USE_ODBX */ return EX_DATAERR; } else if (reporter == NULL) { fprintf(stderr, "%s: could not locate receiving host in Received header field\n", progname); #ifdef USE_ODBX if (db != NULL) { (void) odbx_unbind(db); (void) odbx_finish(db); } else { #endif /* USE_ODBX */ fclose(sf); #ifdef USE_ODBX } #endif /* USE_ODBX */ return EX_DATAERR; } for (p = job; *p != '\0'; p++) { if (*p == ';') { *p = '\0'; break; } } if (sf != NULL) { fprintf(sf, "U%s\t%s\t0\t1\n", job, reporter); fclose(sf); return 0; } #ifdef USE_ODBX if (verbose >= 1) { fprintf(stdout, "%s: requesting reporter id for '%s'\n", progname, reporter); } if (dofork) { pid_t pid; pid = fork(); switch (pid) { case -1: fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_OSERR; case 0: (void) setsid(); /* XXX -- should probably dup2() /dev/null here */ break; default: return 0; } } /* retrieve reporter ID */ snprintf(buf, sizeof buf, "SELECT id FROM reporters WHERE name = '%s'", reporter); if (verbose >= 3) fprintf(stdout, ">>> %s\n", buf); dberr = odbx_query(db, buf, 0); if (dberr != ODBX_ERR_SUCCESS) { fprintf(stderr, "%s: odbx_query(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } repid = -1; while ((dberr = odbx_result(db, &result, NULL, 0)) != ODBX_RES_DONE) { if (dberr < 0) { fprintf(stderr, "%s: odbx_result(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } switch (dberr) { case ODBX_RES_TIMEOUT: fprintf(stderr, "%s: odbx_result(): timeout\n", progname); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; case ODBX_RES_NOROWS: fprintf(stderr, "%s: odbx_result(): unexpected return value\n", progname); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; case ODBX_RES_ROWS: while ((dberr = odbx_row_fetch(result)) != ODBX_ROW_DONE) { if (dberr < 0) { fprintf(stderr, "%s: odbx_row_fetch(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } if (repid != -1) { fprintf(stderr, "%s: duplicate entries for repoter '%s'\n", progname, reporter); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } repid = atoi(odbx_field_value(result, 0)); if (repid <= 0) { fprintf(stderr, "%s: unexpected reporter id '%s'\n", progname, odbx_field_value(result, 0)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } } break; default: assert(0); } } (void) odbx_result_finish(result); if (repid <= 0) { fprintf(stderr, "%s: could not determine reporter id for '%s'\n", progname, reporter); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_DATAERR; } if (verbose >= 2) fprintf(stdout, "%s: reporter id = %d\n", progname, repid); if (verbose >= 1) { fprintf(stdout, "%s: requesting message id for '%s'\n", progname, job); } /* get message ID */ snprintf(buf, sizeof buf, "SELECT MAX(id) FROM messages WHERE jobid = '%s' AND reporter = %d", job, repid); if (verbose >= 3) fprintf(stdout, ">>> %s\n", buf); dberr = odbx_query(db, buf, 0); if (dberr != ODBX_ERR_SUCCESS) { fprintf(stderr, "%s: odbx_query(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } msgid = -1; while ((dberr = odbx_result(db, &result, NULL, 0)) != ODBX_RES_DONE) { if (dberr < 0) { fprintf(stderr, "%s: odbx_result(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } switch (dberr) { case ODBX_RES_TIMEOUT: fprintf(stderr, "%s: odbx_result(): timeout\n", progname); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; case ODBX_RES_NOROWS: fprintf(stderr, "%s: odbx_result(): unexpected return value\n", progname); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; case ODBX_RES_ROWS: while ((dberr = odbx_row_fetch(result)) != ODBX_ROW_DONE) { if (dberr < 0) { fprintf(stderr, "%s: odbx_row_fetch(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } if (msgid != -1) { fprintf(stderr, "%s: duplicate entries for job '%s' from reporter '%s'\n", progname, job, reporter); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } msgid = atoi(odbx_field_value(result, 0)); if (msgid <= 0) { fprintf(stderr, "%s: unexpected message id '%s'\n", progname, odbx_field_value(result, 0)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } } break; default: assert(0); } } (void) odbx_result_finish(result); if (msgid <= 0) { fprintf(stderr, "%s: could not determine message id for '%s'\n", progname, job); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_DATAERR; } if (verbose >= 2) fprintf(stdout, "%s: message id = %d\n", progname, msgid); /* issue update */ if (verbose >= 1) fprintf(stdout, "%s: updating record\n", progname); snprintf(buf, sizeof buf, "UPDATE messages SET %s = %s + 1 WHERE id = %d AND %s >= 0", dbspamcol, dbspamcol, msgid, dbspamcol); if (verbose >= 3) fprintf(stdout, ">>> %s\n", buf); dberr = odbx_query(db, buf, 0); if (dberr != ODBX_ERR_SUCCESS) { fprintf(stderr, "%s: odbx_query(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } for (;;) { dberr = odbx_result(db, &result, NULL, 0); if (dberr == ODBX_RES_DONE || dberr == ODBX_RES_NOROWS) { break; } else if (dberr < 0) { fprintf(stderr, "%s: odbx_result(): %s\n", progname, odbx_error(db, dberr)); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; } switch (dberr) { case ODBX_RES_TIMEOUT: fprintf(stderr, "%s: odbx_result(): timeout\n", progname); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; case ODBX_RES_ROWS: fprintf(stderr, "%s: odbx_result(): unexpected return value\n", progname); (void) odbx_unbind(db); (void) odbx_finish(db); return EX_SOFTWARE; default: assert(0); } } (void) odbx_result_finish(result); if (verbose >= 1) fprintf(stdout, "%s: record updated\n", progname); /* close down */ (void) odbx_unbind(db); (void) odbx_finish(db); #endif /* USE_ODBX */ return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-stats.8.in000066400000000000000000000012641337314105200237260ustar00rootroot00000000000000.TH OPENDKIM-STATS 8 "The Trusted Domain Project" .SH NAME .B opendkim-stats \- output opendkim statistics .SH SYNOPSIS .B opendkim-stats .I file .SH DESCRIPTION The .B opendkim-stats utility reads from an .I opendkim statistics database and dumps the data therein to standard output. It takes as its only argument the path to this database. The .I opendkim statistics gathering is disabled by default, but can be enabled through a .I Statistics entry in .I @SYSCONFDIR@/opendkim.conf. See the .I opendkim.conf(5) man page for details. .SH SEE ALSO .I opendkim(8), opendkim.conf(5) .SH VERSION This man page covers the .I opendkim-stats that shipped with version @VERSION@ of .I OpenDKIM. OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-stats.c000066400000000000000000000202111337314105200233650ustar00rootroot00000000000000/* ** Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. ** */ /* system includes */ #include #include #include #include #include #include #include #include #include #include /* OpenDKIM includes */ #include "build-config.h" #include "stats.h" /* libopendkim includes */ #include /* macros, definitions */ #define MAXLINE 2048 #ifndef MAX # define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif /* ! MAX */ /* globals */ char *progname; /* ** USAGE -- print usage message and exit ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [statsfile]\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int c; int n; int m = 0; int s = 0; int ms = 0; int nfields = 0; int line; int syntax = 0; char *p; char *infile = NULL; char **fields = NULL; FILE *in; char buf[MAXLINE + 1]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; if (argc == 2) infile = argv[1]; else if (argc != 1) return usage(); if (infile != NULL) { in = fopen(infile, "r"); if (in == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, infile, strerror(errno)); return EX_UNAVAILABLE; } } else { in = stdin; } /* initialize stuff */ memset(buf, '\0', sizeof buf); line = 0; /* read lines from stdin */ while (fgets(buf, sizeof buf - 1, in) != NULL) { line++; /* eat the newline */ for (p = buf; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; break; } } /* first byte identifies the record type */ c = buf[0]; /* reset fields array */ if (fields != NULL) memset(fields, '\0', sizeof(char *) * nfields); /* now break out the fields */ n = 0; for (p = strtok(buf + 1, "\t"); p != NULL; p = strtok(NULL, "\t")) { if (nfields == n) { int newnf; size_t newsz; char **new; newnf = MAX(nfields * 2, 8); newsz = sizeof(char *) * newnf; if (nfields == 0) new = (char **) malloc(newsz); else new = (char **) realloc(fields, newsz); if (new == NULL) { fprintf(stderr, "%s: %salloc(): %s\n", progname, fields == NULL ? "m" : "re", strerror(errno)); return EX_OSERR; } nfields = newnf; fields = new; } fields[n++] = p; } /* processing section for version tags */ if (c == 'V') { int inversion; if (n != 1) { fprintf(stderr, "%s: unexpected version field count (%d) at input line %d\n", progname, n, line); continue; } inversion = atoi(fields[0]); if (inversion != DKIMS_VERSION) { fprintf(stderr, "%s: unknown version (%d) at input line %d\n", progname, inversion, line); continue; } } /* processing section for messages */ else if (c == 'M') { time_t rtime; #ifdef _FFR_ATPS char *atps; #endif /* _FFR_ATPS */ #ifdef _FFR_REPUTATION char *spam; #endif /* _FFR_REPUTATION */ if (n != DKIMS_MI_MAX + 1) { fprintf(stderr, "%s: unexpected message field count (%d) at input line %d\n", progname, n, line); continue; } /* format the data */ rtime = (time_t) atoi(fields[DKIMS_MI_MSGTIME]); #ifdef _FFR_ATPS atps = "not checked"; if (fields[DKIMS_MI_ATPS][0] == '0') atps = "no match"; else if (fields[DKIMS_MI_ATPS][0] == '1') atps = "match"; #endif /* _FFR_ATPS */ #ifdef _FFR_REPUTATION spam = "unknown"; if (fields[DKIMS_MI_SPAM][0] == '0') spam = "not spam"; else if (fields[DKIMS_MI_SPAM][0] == '1') spam = "spam"; #endif /* _FFR_REPUTATION */ if (ms > 0) { fprintf(stdout, "\n"); ms = 0; } fprintf(stdout, "Job %s at %s (size %s)\n\treceived via %s at %s\tfrom domain = '%s'\n", fields[DKIMS_MI_JOBID], fields[DKIMS_MI_REPORTER], fields[DKIMS_MI_MSGLEN], fields[DKIMS_MI_IPADDR], ctime(&rtime), fields[DKIMS_MI_FROMDOMAIN]); #ifdef _FFR_ATPS fprintf(stdout, "\tATPS %s\n", atps); #endif /* _FFR_ATPS */ #ifdef _FFR_REPUTATION fprintf(stdout, "\tSpam: %s\n", spam); #endif /* _FFR_REPUTATION */ m++; } /* processing section for signatures */ else if (c == 'S') { char *sigstat; char *siglen; char *dnssec; if (n != DKIMS_SI_MAX + 1) { fprintf(stderr, "%s: unexpected signature field count (%d) at input line %d\n", progname, n, line); continue; } else if (m == 0) { fprintf(stderr, "%s: signature record before message record at input line %d\n", progname, line); continue; } ms++; /* format output */ if (fields[DKIMS_SI_PASS][0] == '1') sigstat = "PASSED"; else if (fields[DKIMS_SI_FAIL_BODY][0] == '1') sigstat = "FAILED (body changed)"; else if (atoi(fields[DKIMS_SI_SIGERROR]) == DKIM_SIGERROR_KEYREVOKED) sigstat = "REVOKED"; else if (fields[DKIMS_SI_SIGERROR][0] != '0') sigstat = "ERROR"; else sigstat = "UNKNOWN"; if (fields[DKIMS_SI_SIGLENGTH][0] == '-') siglen = "(whole message)"; else siglen = fields[DKIMS_SI_SIGLENGTH]; switch (fields[DKIMS_SI_DNSSEC][0]) { case '-': dnssec = "UNKNOWN"; break; case '0': dnssec = "BOGUS"; break; case '1': dnssec = "INSECURE"; break; case '2': dnssec = "SECURE"; break; } syntax = atoi(fields[DKIMS_SI_SIGERROR]); syntax = (syntax == DKIM_SIGERROR_VERSION || syntax == DKIM_SIGERROR_DOMAIN || syntax == DKIM_SIGERROR_TIMESTAMPS || syntax == DKIM_SIGERROR_INVALID_HC || syntax == DKIM_SIGERROR_INVALID_BC || syntax == DKIM_SIGERROR_MISSING_A || syntax == DKIM_SIGERROR_INVALID_A || syntax == DKIM_SIGERROR_MISSING_H || syntax == DKIM_SIGERROR_INVALID_L || syntax == DKIM_SIGERROR_INVALID_Q || syntax == DKIM_SIGERROR_INVALID_QO || syntax == DKIM_SIGERROR_MISSING_D || syntax == DKIM_SIGERROR_EMPTY_D || syntax == DKIM_SIGERROR_MISSING_S || syntax == DKIM_SIGERROR_EMPTY_S || syntax == DKIM_SIGERROR_MISSING_B || syntax == DKIM_SIGERROR_EMPTY_B || syntax == DKIM_SIGERROR_CORRUPT_B || syntax == DKIM_SIGERROR_MISSING_BH || syntax == DKIM_SIGERROR_EMPTY_BH || syntax == DKIM_SIGERROR_CORRUPT_BH || syntax == DKIM_SIGERROR_EMPTY_H || syntax == DKIM_SIGERROR_INVALID_H || syntax == DKIM_SIGERROR_TOOLARGE_L || syntax == DKIM_SIGERROR_MBSFAILED); fprintf(stdout, "\tSignature %d from %s\n\t\t%s\n\t\tsigned bytes: %s\n\t\tSignature properties: %s\n\t\tKey properties: %s %s\n\t\tDNSSEC status: %s\n", ms, fields[DKIMS_SI_DOMAIN], sigstat, siglen, atoi(fields[DKIMS_SI_SIGERROR]) == DKIM_SIGERROR_FUTURE ? "t=future" : "", syntax != 0 ? "syntax" : "", atoi(fields[DKIMS_SI_SIGERROR]) == DKIM_SIGERROR_NOKEY ? "NXDOMAIN" : "", dnssec); s++; } #ifdef _FFR_STATSEXT /* processing section for extension data */ else if (c == 'X') { fprintf(stdout, "\tExtension data: %s=%s\n", fields[0], fields[1]); } #endif /* _FFR_STATSEXT */ /* unknown record type */ else { fprintf(stderr, "%s: unknown record type '%c' at input line %d\n", progname, c, line); } } if (ferror(in)) { fprintf(stderr, "%s: fgets(): %s at input line %d\n", progname, strerror(errno), line); } if (infile != NULL) fclose(in); fprintf(stdout, "%s: %d message%s, %d signature%s processed\n", progname, m, m == 0 ? "" : "s", s, s == 0 ? "" : "s"); return EX_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-testkey.8.in000066400000000000000000000045051337314105200242610ustar00rootroot00000000000000.TH opendkim-testkey 8 "The Trusted Domain Project" .SH NAME .B opendkim-testkey \- DKIM filter installation test .SH SYNOPSIS .B opendkim-testkey [\-d domain] [\-s selector] [\-k keypath] [\-v] [\-x configfile] .SH DESCRIPTION .B opendkim-testkey verifies the setup of signing and verifying (private and public) keys for use with .I opendkim(8). The test program will read a domain name and selector from the command line, configuration file or a key table, then query and parse the resulting DKIM key(s), reporting any errors found. If a key path is also provided, the test program will read the private key named and attempt to confirm that the private key specified by .I keypath (or in the key table) and the public DKIM key retrieved match. .SH OPTIONS .TP .I -d domain Names the domain in which signing is to be done. More specifically, names the domain in which the public key matching the provided private key will be found. This parameter must be provided either explicitly, or in the configuration file, or via a KeyTable (see .I opendkim.conf(5) for details). .TP .I -k keypath Specifies the path to the private key file which should be used for this test. This parameter is optional .TP .I -s selector Names the selector within the specified domain whose public key should be retrieved and tested, comparing it to the private key if provided. This parameter must be provided either explicitly, or in the configuration file, or via a KeyTable (see .I opendkim.conf(5) for details). .TP .I -v Increases the amount of output (verbosity) of the program. May be specified multiple times for increased output. .TP .I -x conffile Names a configuration file to be parsed. See the .I opendkim.conf(5) man page for details. The only values used are Domain, Selector, KeyFile, KeyTable, TrustAnchorFile and ResolverConfig. The default is .I @SYSCONFDIR@/opendkim.conf. .SH NOTES The test program will also complain if a private key file is readable by anyone other than the user executing the program. .SH VERSION This man page covers the version of .I opendkim-testkey that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2007, 2008, Sendmail, Inc. and its suppliers. All rights reserved. Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-testkey.c000066400000000000000000000366401337314105200237340ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* for Solaris */ #ifndef _REENTRANT # define _REENTRANT #endif /* _REENTRANT */ /* system includes */ #include #include #include #include #include #include #include #include #include #include #ifdef USE_GNUTLS /* gcrypt includes */ # include #else /* USE_GNUTLS */ /* openssl includes */ # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "opendkim-db.h" #include "opendkim-dns.h" #include "config.h" #include "opendkim-config.h" #include "opendkim-crypto.h" /* macros */ #define CMDLINEOPTS "d:k:s:vx:" #define DEFCONFFILE CONFIG_BASE "/opendkim.conf" #define MAXBUFRSZ 65536 #define BUFRSZ 2048 #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* !MIN */ /* prototypes */ void dkimf_log_ssl_errors(void); int usage(void); /* globals */ char *progname; #ifdef USE_UNBOUND struct dkimf_unbound *unbound; /* libunbound handle */ #endif /* USE_UNBOUND */ /* ** DKIMF_LOG_SSL_ERRORS -- log any queued SSL library errors ** ** Parameters: ** jobid -- job ID to include in log messages ** ** Return value: ** None. */ void dkimf_log_ssl_errors(void) { #ifdef USE_GNUTLS const char *err; err = dkimf_crypto_geterror(); if (err != NULL) fprintf(stderr, "%s\n", err); #else /* USE_GNUTLS */ /* log any queued SSL error messages */ if (ERR_peek_error() != 0) { int n; int saveerr; u_long e; char errbuf[BUFRSZ + 1]; char tmp[BUFRSZ + 1]; saveerr = errno; memset(errbuf, '\0', sizeof errbuf); for (n = 0; ; n++) { e = ERR_get_error(); if (e == 0) break; memset(tmp, '\0', sizeof tmp); (void) ERR_error_string_n(e, tmp, sizeof tmp); if (n != 0) strlcat(errbuf, "; ", sizeof errbuf); strlcat(errbuf, tmp, sizeof errbuf); } fprintf(stderr, "%s\n", errbuf); errno = saveerr; } #endif /* ! USE_GNUTLS */ } /* ** LOADKEY -- resolve a key ** ** Parameters: ** buf -- key buffer ** buflen -- pointer to key buffer's length (updated) ** ** Return value: ** TRUE on successful load, false otherwise */ int loadkey(char *buf, size_t *buflen) { assert(buf != NULL); assert(buflen != NULL); if (buf[0] == '/' || (buf[0] == '.' && buf[1] == '/') || (buf[0] == '.' && buf[1] == '.' && buf[2] == '/')) { int fd; int status; ssize_t rlen; struct stat s; fd = open(buf, O_RDONLY); if (fd < 0) return FALSE; status = fstat(fd, &s); if (status != 0) { close(fd); return FALSE; } *buflen = MIN(s.st_size, *buflen); rlen = read(fd, buf, *buflen); close(fd); if (rlen < *buflen) return FALSE; } else { *buflen = strlen(buf); } return TRUE; } /* ** USAGE -- print a usage message ** ** Parameters: ** None. ** ** Return value: ** EX_CONFIG */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\n" "\t-d domain \tdomain name\n" "\t-k keypath \tpath to private key\n" "\t-s selector\tselector name\n" "\t-v \tincrease verbose output\n" "\t-x conffile\tconfiguration file\n", progname, progname); return EX_CONFIG; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int status; int fd; int len; int c; int verbose = 0; int argv_d = 0; int argv_s = 0; int argv_k = 0; int dnssec; char *key = NULL; char *dataset = NULL; char *nslist = NULL; char *conffile = NULL; char *p; DKIM_LIB *lib; char *trustanchor = NULL; char *nsconfig = NULL; struct stat s; char err[BUFRSZ]; char domain[BUFRSZ]; char selector[BUFRSZ]; char keypath[MAXBUFRSZ]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; memset(domain, '\0', sizeof domain); memset(selector, '\0', sizeof selector); memset(keypath, '\0', sizeof keypath); while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) { switch (c) { case 'd': strlcpy(domain, optarg, sizeof domain); argv_d = 1; break; case 'k': strlcpy(keypath, optarg, sizeof keypath); argv_k = 1; break; case 's': strlcpy(selector, optarg, sizeof selector); argv_s = 1; break; case 'v': verbose++; break; case 'x': conffile = optarg; break; default: return usage(); } } /* process config file */ if (conffile == NULL && access(DEFCONFFILE, R_OK) == 0) { conffile = DEFCONFFILE; if (verbose > 1) { fprintf(stderr, "%s: using default configfile %s\n", progname, DEFCONFFILE); } } if (conffile != NULL) { #ifdef USE_LDAP _Bool ldap_usetls = FALSE; #endif /* USE_LDAP */ u_int line = 0; #ifdef USE_LDAP char *ldap_authmech = NULL; # ifdef USE_SASL char *ldap_authname = NULL; char *ldap_authrealm = NULL; char *ldap_authuser = NULL; # endif /* USE_SASL */ char *ldap_bindpw = NULL; char *ldap_binduser = NULL; #endif /* USE_LDAP */ struct config *cfg; char path[MAXPATHLEN + 1]; cfg = config_load(conffile, dkimf_config, &line, path, sizeof path, NULL); if (cfg == NULL) { fprintf(stderr, "%s: %s: configuration error at line %u\n", progname, path, line); return EX_CONFIG; } (void) config_get(cfg, "KeyTable", &dataset, sizeof dataset); if (domain[0] == '\0') { p = NULL; (void) config_get(cfg, "Domain", &p, sizeof p); if (p != NULL) strlcpy(domain, p, sizeof domain); } if (selector[0] == '\0') { p = NULL; (void) config_get(cfg, "Selector", &p, sizeof p); if (p != NULL) strlcpy(selector, p, sizeof selector); } if (keypath[0] == '\0') { p = NULL; (void) config_get(cfg, "KeyFile", &p, sizeof p); if (p != NULL) strlcpy(keypath, p, sizeof keypath); } #ifdef USE_LDAP (void) config_get(cfg, "LDAPUseTLS", &ldap_usetls, sizeof ldap_usetls); if (ldap_usetls) dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "y"); else dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "n"); (void) config_get(cfg, "LDAPAuthMechanism", &ldap_authmech, sizeof ldap_authmech); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHMECH, ldap_authmech); # ifdef USE_SASL (void) config_get(cfg, "LDAPAuthName", &ldap_authname, sizeof ldap_authname); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHNAME, ldap_authname); (void) config_get(cfg, "LDAPAuthRealm", &ldap_authrealm, sizeof ldap_authrealm); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHREALM, ldap_authrealm); (void) config_get(cfg, "LDAPAuthUser", &ldap_authuser, sizeof ldap_authuser); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHUSER, ldap_authuser); # endif /* USE_SASL */ (void) config_get(cfg, "LDAPBindPassword", &ldap_bindpw, sizeof ldap_bindpw); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDPW, ldap_bindpw); (void) config_get(cfg, "LDAPBindUser", &ldap_binduser, sizeof ldap_binduser); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDUSER, ldap_binduser); #endif /* USE_LDAP */ (void) config_get(cfg, "TrustAnchorFile", &trustanchor, sizeof trustanchor); (void) config_get(cfg, "ResolverConfiguration", &nsconfig, sizeof nsconfig); (void) config_get(cfg, "Nameservers", &nslist, sizeof nslist); } lib = dkim_init(NULL, NULL); if (lib == NULL) { fprintf(stderr, "%s: dkim_init() failed\n", progname); (void) free(key); return EX_OSERR; } #ifdef USE_UNBOUND (void) dkimf_unbound_setup(lib); #endif /* USE_UNBOUND */ if (dkim_dns_init(lib) != DKIM_STAT_OK) { fprintf(stderr, "%s: dkim_dns_init() failed\n", progname); (void) free(key); return EX_SOFTWARE; } if (nslist != NULL) status = dkimf_dns_setnameservers(lib, nslist); if (trustanchor != NULL) { status = dkimf_dns_trustanchor(lib, trustanchor); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: failed to set trust anchor\n", progname); (void) free(key); return EX_OSERR; } } if (nsconfig != NULL) { status = dkimf_dns_config(lib, nsconfig); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: failed to set unbound configuration file\n", progname); (void) free(key); return EX_OSERR; } } memset(err, '\0', sizeof err); #ifndef USE_GNUTLS ERR_load_crypto_strings(); #endif /* ! USE_GNUTLS */ /* process a KeyTable if specified and not overridden */ if (dataset != NULL && argv_d == 0 && argv_k == 0 && argv_s == 0) { int c; int pass = 0; int fail = 0; size_t keylen; DKIMF_DB db; char keyname[BUFRSZ + 1]; struct dkimf_db_data dbd[3]; memset(dbd, '\0', sizeof dbd); status = dkimf_db_open(&db, dataset, DKIMF_DB_FLAG_READONLY, NULL, NULL); if (status != 0) { fprintf(stderr, "%s: dkimf_db_open() failed\n", progname); return 1; } if (dkimf_db_type(db) == DKIMF_DB_TYPE_REFILE) { fprintf(stderr, "%s: invalid data set type\n", progname); (void) dkimf_db_close(db); return 1; } for (c = 0; ; c++) { memset(keyname, '\0', sizeof keyname); memset(domain, '\0', sizeof domain); memset(selector, '\0', sizeof selector); memset(keypath, '\0', sizeof keypath); dbd[0].dbdata_buffer = domain; dbd[0].dbdata_buflen = sizeof domain; dbd[1].dbdata_buffer = selector; dbd[1].dbdata_buflen = sizeof selector; dbd[2].dbdata_buffer = keypath; dbd[2].dbdata_buflen = sizeof keypath; keylen = sizeof keyname; status = dkimf_db_walk(db, c == 0, keyname, &keylen, dbd, 3); if (status == -1) { fprintf(stderr, "%s: dkimf_db_walk(%d) failed\n", progname, c); (void) dkimf_db_close(db); return 1; } else if (status == 1) { (void) dkimf_db_close(db); break; } if (verbose > 1) { fprintf(stderr, "%s: record %d for '%s' retrieved\n", progname, c, keyname); } if (keypath[0] == '/' || strncmp(keypath, "./", 2) == 0 || strncmp(keypath, "../", 3) == 0) { status = stat(keypath, &s); if (status != 0) { fprintf(stderr, "%s: %s: stat(): %s\n", progname, keypath, strerror(errno)); return EX_OSERR; } if (!S_ISREG(s.st_mode)) { fprintf(stderr, "%s: %s: stat(): not a regular file\n", progname, keypath); return EX_OSERR; } /* XXX -- should also check directories up the chain */ if ((s.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) { fprintf(stderr, "%s: %s: WARNING: unsafe permissions\n", progname, keypath); } } keylen = sizeof keypath; if (!loadkey(keypath, &keylen)) { fprintf(stderr, "%s: load of key '%s' failed\n", progname, keyname); (void) dkimf_db_close(db); return 1; } if (verbose > 1) { fprintf(stderr, "%s: checking key '%s'\n", progname, keyname); } dnssec = DKIM_DNSSEC_UNKNOWN; status = dkim_test_key(lib, selector, domain, keypath, keylen, &dnssec, err, sizeof err); switch (status) { case -1: case 1: fprintf(stderr, "%s: key %s: %s\n", progname, keyname, err); fail++; dkimf_log_ssl_errors(); break; case 0: if (verbose > 2) { fprintf(stdout, "%s: key %s: OK\n", progname, keyname); } pass++; break; default: assert(0); } switch (dnssec) { case DKIM_DNSSEC_INSECURE: if (verbose > 0) { fprintf(stderr, "%s: key %s not secure\n", progname, keyname); } break; case DKIM_DNSSEC_SECURE: if (verbose > 0) { fprintf(stderr, "%s: key %s secure\n", progname, keyname); } break; case DKIM_DNSSEC_BOGUS: fprintf(stderr, "%s: key %s bogus (DNSSEC failed)\n", progname, keyname); break; case DKIM_DNSSEC_UNKNOWN: default: break; } } if (verbose > 0) { fprintf(stdout, "%s: %d key%s checked; %d pass, %d fail\n", progname, c, c == 1 ? "" : "s", pass, fail); } (void) dkim_close(lib); return 0; } if (domain[0] == '\0' || selector[0] == '\0') return usage(); memset(&s, '\0', sizeof s); if (keypath[0] != '\0') { status = stat(keypath, &s); if (status != 0) { fprintf(stderr, "%s: %s: stat(): %s\n", progname, keypath, strerror(errno)); return EX_OSERR; } if (!S_ISREG(s.st_mode)) { fprintf(stderr, "%s: %s: stat(): not a regular file\n", progname, keypath); return EX_OSERR; } /* XXX -- should also check directories up the chain */ if ((s.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) { fprintf(stderr, "%s: %s: WARNING: unsafe permissions\n", progname, keypath); } key = malloc(s.st_size); if (key == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_OSERR; } fd = open(keypath, O_RDONLY, 0); if (fd < 0) { fprintf(stderr, "%s: %s: open(): %s\n", progname, keypath, strerror(errno)); (void) free(key); return EX_OSERR; } len = read(fd, key, s.st_size); if (len < 0) { fprintf(stderr, "%s: %s: read(): %s\n", progname, keypath, strerror(errno)); (void) close(fd); (void) free(key); return EX_OSERR; } else if (len < s.st_size) { fprintf(stderr, "%s: %s: read() truncated (expected %ld, got %d)\n", progname, keypath, (long) s.st_size, len); (void) close(fd); (void) free(key); return EX_OSERR; } (void) close(fd); if (verbose > 1) { fprintf(stderr, "%s: key loaded from %s\n", progname, keypath); } } dnssec = DKIM_DNSSEC_UNKNOWN; if (verbose > 1) { fprintf(stderr, "%s: checking key '%s._domainkey.%s'\n", progname, selector, domain); } status = dkim_test_key(lib, selector, domain, key, (size_t) s.st_size, &dnssec, err, sizeof err); (void) dkim_close(lib); switch (dnssec) { case DKIM_DNSSEC_INSECURE: if (verbose > 0) fprintf(stderr, "%s: key not secure\n", progname); break; case DKIM_DNSSEC_SECURE: if (verbose > 0) fprintf(stderr, "%s: key secure\n", progname); break; case DKIM_DNSSEC_BOGUS: fprintf(stderr, "%s: key bogus (DNSSEC failed)\n", progname); break; case DKIM_DNSSEC_UNKNOWN: default: break; } switch (status) { case -1: fprintf(stderr, "%s: %s\n", progname, err); dkimf_log_ssl_errors(); return EX_UNAVAILABLE; case 0: if (verbose > 2) fprintf(stdout, "%s: key OK\n", progname); return EX_OK; case 1: fprintf(stdout, "%s: %s\n", progname, err); dkimf_log_ssl_errors(); return EX_DATAERR; } return 0; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-testmsg.8.in000066400000000000000000000036671337314105200242670ustar00rootroot00000000000000.TH opendkim-testmsg 8 "The Trusted Domain Project" .SH NAME .B opendkim-testmsg \- DKIM message tst .SH SYNOPSIS .B opendkim-testmsg [\-C] [\-d domain] [\-K] [\-k keypath] [\-s selector] [\-t path] .SH DESCRIPTION .B opendkim-testmsg signs or verifies an input message. This is similar to the test mode for .I opendkim(8) except that it does not use the same configuration system or milter interface. Rather, it is a direct access to the DKIM library with those functions "out of the way". The message is read from standard input. In signing mode, the complete signed message will then be written to standard output. When verifying, there will be no output unless an error occurred. To sign a message, the \-d, \-k and \-s settings in the SYNOPSIS above must be provided. If all of them are absent, the input message will be verified. If some but not all are present, an error is returned. .SH OPTIONS .TP .I -C If specified, the signature header field generated in signing mode will be line-terminated with carriage-return line-feed, instead of just line-feed. .TP .I -d domain Names the domain in which signing is to be done. More specifically, names the domain in which the public key matching the provided private key would be found in a live test. .TP .I -K Arranges to keep temporary files generated during message canonicalization for debugging purposes. .TP .I -k keypath Specifies the path to the private key file which should be used to sign the input message. .TP .I -s selector Names the selector within the specified domain that should be included in the signature. .TP .I -t path Specifies the directory in which temporary files are to be created. The default is .I /tmp. .SH VERSION This man page covers the version of .I opendkim-testmsg that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011-2013, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim-testmsg.c000066400000000000000000000170561337314105200237320ustar00rootroot00000000000000/* ** Copyright (c) 2011-2013, 2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #ifdef USE_GNUTLS # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include /* macros */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ #define BUFRSZ 1024 #define DEFTMPDIR "/tmp" #define CMDLINEOPTS "Cd:Kk:s:t:" #define STRORNULL(x) ((x) == NULL ? "(null)" : (x)) #define TMPTEMPLATE "dkimXXXXXX" /* prototypes */ int usage(void); /* globals */ char *progname; /* ** USAGE -- print a usage message ** ** Parameters: ** None. ** ** Return value: ** EX_CONFIG */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\nValid options:\n" "\t-C \tpreserve CRLFs\n" "\t-d domain \tset signing domain\n" "\t-K \tkeep temporary files\n" "\t-k keyfile \tprivate key file\n" "\t-s selector\tset signing selector\n" "\t-t path \tdirectory for temporary files\n", progname, progname); return EX_CONFIG; } /* ** DECR -- remove CRs from a string ** ** Parameters: ** str -- string to modify; must be NULL-terminated ** ** Return value: ** None. */ void decr(char *str) { char *p; char *q; for (p = str, q = str; *p != '\0'; p++) { if (*p == '\r') continue; if (p != q) *q = *p; q++; } } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { _Bool keepcrlf = FALSE; _Bool keepfiles = FALSE; _Bool testkey = FALSE; int c; int n = 0; int tfd; u_int flags; DKIM_STAT status; ssize_t rlen; ssize_t wlen; ssize_t l = (ssize_t) -1; dkim_alg_t sa = DKIM_SIGN_RSASHA1; dkim_canon_t bc = DKIM_CANON_SIMPLE; dkim_canon_t hc = DKIM_CANON_RELAXED; DKIM_LIB *lib; DKIM *dkim; char *p; const char *domain = NULL; const char *selector = NULL; const char *keyfile = NULL; char *keydata = NULL; char *tmpdir = DEFTMPDIR; char buf[BUFRSZ]; char fn[BUFRSZ]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) { switch (c) { case 'C': keepcrlf = TRUE; break; case 'd': domain = optarg; n++; break; case 'K': keepfiles = TRUE; break; case 'k': keyfile = optarg; n++; break; case 's': selector = optarg; n++; break; case 't': tmpdir = optarg; break; default: return usage(); } } if (n != 0 && n != 3) return usage(); memset(fn, '\0', sizeof fn); snprintf(fn, sizeof fn, "%s/%s", tmpdir, TMPTEMPLATE); if (n == 3) { int fd; struct stat s; fd = open(keyfile, O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: %s: open(): %s\n", progname, keyfile, strerror(errno)); return EX_OSERR; } if (fstat(fd, &s) != 0) { fprintf(stderr, "%s: %s: fstat(): %s\n", progname, keyfile, strerror(errno)); close(fd); return EX_OSERR; } keydata = malloc(s.st_size + 1); if (keydata == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); close(fd); return EX_OSERR; } memset(keydata, '\0', s.st_size + 1); rlen = read(fd, keydata, s.st_size); if (rlen == -1) { fprintf(stderr, "%s: %s: read(): %s\n", progname, keyfile, strerror(errno)); close(fd); free(keydata); return EX_OSERR; } else if (rlen < s.st_size) { fprintf(stderr, "%s: %s: read() truncated (got %lu, expected %lu)\n", progname, keyfile, (unsigned long) rlen, (unsigned long) s.st_size); close(fd); free(keydata); return EX_DATAERR; } close(fd); } #ifdef USE_GNUTLS (void) gnutls_global_init(); #endif /* USE_GNUTLS */ lib = dkim_init(NULL, NULL); if (lib == NULL) { fprintf(stderr, "%s: dkim_init() failed\n", progname); return EX_SOFTWARE; } if (n == 0) { dkim = dkim_verify(lib, progname, NULL, &status); if (dkim == NULL) { fprintf(stderr, "%s: dkim_verify() failed: %s\n", progname, dkim_getresultstr(status)); dkim_close(lib); return EX_SOFTWARE; } } else { dkim = dkim_sign(lib, progname, NULL, keydata, selector, domain, hc, bc, sa, l, &status); if (dkim == NULL) { fprintf(stderr, "%s: dkim_sign() failed: %s\n", progname, dkim_getresultstr(status)); if (keydata != NULL) free(keydata); dkim_close(lib); return EX_SOFTWARE; } } /* set flags */ flags = (DKIM_LIBFLAGS_FIXCRLF|DKIM_LIBFLAGS_STRICTHDRS); if (keepfiles) flags |= (DKIM_LIBFLAGS_TMPFILES|DKIM_LIBFLAGS_KEEPFILES); (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &flags, sizeof flags); tfd = mkstemp(fn); if (tfd < 0) { fprintf(stderr, "%s: mkstemp(): %s\n", progname, strerror(errno)); if (keydata != NULL) free(keydata); dkim_close(lib); return EX_SOFTWARE; } (void) unlink(fn); for (;;) { rlen = fread(buf, 1, sizeof buf, stdin); if (ferror(stdin)) { fprintf(stderr, "%s: fread(): %s\n", progname, strerror(errno)); dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_SOFTWARE; } if (rlen > 0) { wlen = write(tfd, buf, rlen); if (wlen == -1) { fprintf(stderr, "%s: %s: write(): %s\n", progname, fn, strerror(errno)); dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_SOFTWARE; } status = dkim_chunk(dkim, buf, rlen); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: dkim_chunk(): %s\n", progname, dkim_getresultstr(status)); dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_SOFTWARE; } } if (feof(stdin)) break; } status = dkim_chunk(dkim, NULL, 0); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: dkim_chunk(): %s\n", progname, dkim_getresultstr(status)); dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_SOFTWARE; } status = dkim_eom(dkim, &testkey); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: dkim_eom(): %s\n", progname, dkim_getresultstr(status)); dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_SOFTWARE; } if (n == 0) { /* XXX -- do a policy query */ } else { unsigned char *sighdr; size_t siglen; /* extract signature */ status = dkim_getsighdr_d(dkim, strlen(DKIM_SIGNHEADER), &sighdr, &siglen); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: dkim_getsighdr_d(): %s\n", progname, dkim_getresultstr(status)); dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_SOFTWARE; } /* print it and the message */ if (!keepcrlf) decr(sighdr); fprintf(stdout, "%s: %s%s\n", DKIM_SIGNHEADER, sighdr, keepcrlf ? "\r" : ""); (void) lseek(tfd, 0, SEEK_SET); for (;;) { rlen = read(tfd, buf, sizeof buf); (void) fwrite(buf, 1, rlen, stdout); if (rlen < sizeof buf) break; } } dkim_free(dkim); dkim_close(lib); close(tfd); if (keydata != NULL) free(keydata); return EX_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.8.in000066400000000000000000000540151337314105200225740ustar00rootroot00000000000000.TH opendkim 8 "The Trusted Domain Project" .SH NAME .B opendkim \- DKIM signing and verifying filter for MTAs .SH SYNOPSIS .B opendkim [\-A] [\-b modes] [\-c canon] [\-d domain[,...]] [\-D] [\-e name] [\-f] [\-F time] [\-k keyfile] [\-l] [\-L min] [\-n] [\-o hdrlist] [\-p socketspec] [\-P pidfile] [\-Q] [\-r] [\-s selector] [\-S signalg] [\-t testfiles] [\-T secs] [\-u userid[:group]] [\-v] [\-V] [\-W] [\-x configfile] [\-X] .SH DESCRIPTION .B opendkim implements the .B DKIM standard for signing and verifying e-mail messages on a per-domain basis. .B opendkim uses the .I milter interface, originally distributed as part of version 8.11 of .B sendmail(8), to provide DKIM signing and/or verifying service for mail transiting a milter-aware MTA. Most, if not all, of the command line options listed below can also be set using a configuration file. See the .I \-x option for details. .SH DATA SETS Many of the command line and configuration file parameters will refer to a "dataset" as their values. This refers to a string that either contains the list of desirable values, or to a file that contains them, or (if enabled at compile time) a database containing the data. Some data sets require that the value contain more than one entry. How this is done depends on which data set type is used. Which type is used depends on the format of the specification string. Note that not all of these are necessarily supported for all installations; most of them depend on the availability of a particular third-party library at compile time. In particular: .TP .I a) If the string begins with "file:", then the remainder of the string is presumed to refer to a flat file that contains elements of the data set, one per line. If a line contains whitespace-separated values, then the line is presumed to define a key and its corresponding value. Blank lines are ignored, and the hash ("#") character denotes the start of a comment. If a value contains multiple entries, the entries should be separated by colons. .TP .I b) If the string begins with "refile:", then the remainder of the string is presumed to specify a file that contains a set of patterns, one per line, and their associated values. The pattern is taken as the start of the line to the first whitespace, and the portion after that whitespace is taken as the value to be used when that pattern is matched. Patterns are simple wildcard patterns, matching all text except that the asterisk ("*") character is considered a wildcard. If a value contains multiple entries, the entries should be separated by colons. .TP .I c) If the string begins with "db:" and the program was compiled with Sleepycat DB support, then the remainder of the string is presumed to identify a Sleepycat database containing keys and corresponding values. These may be used only to test for membership in the data set, or for storing keys and corresponding values. If a value contains multiple entries, the entries should be separated by colons. .TP .I d) If the string begins with "dsn:" and the OpenDKIM library was compiled to support that database type, then the remainder of the string is a Data Store Name describing the type, location parameters and access credentials for an ODBC or SQL database. The DSN is of the form: backend://[user[:pwd]@][port+]host/dbase[/key=value[?...]] where .I backend is the name of a supported backend database mechanism (e.g. "mysql"), .I user and .I password are optional login credentials for the database, .I port and .I host describe the destination of a TCP connection to connect to that database, .I dbase is the name of the database to be accessed, and the .I key=value pairs must specify at least "table", "keycol" and "datacol" values specifying the name of the table, the name of the column to consider as the key, and the name(s) of the column(s) to be considered as the values (separated by commas). For example (all in one line): mysql:://dbuser:dbpass@3306+dbhost/odkim/table=macros .br ?keycol=host?datacol=v1,v2 defines a MySQL database listening at port 3306 on host "dbhost"; the userid "dbuser" and password "dbpass" should be used to access the database; the database name is "odkim", and the data are in columns "host" (the keys) and "v1" and "v2" (the values) inside table "macros". This example would thus return two values when a match is found. The key may also include a "filter" value which will be included in all generated SQL as an AND clause after the WHERE clause that declares the search criteria. For example, given the above DSN specification with an additional "filter" value of "ID > 1000", the generated SQL for a query for "foo" would look like so: SELECT v1,v2 FROM macros WHERE host = 'foo' AND ID > 1000 No value within the DSN may contain any of the six punctuation characters (":", "/", "@", "+", "?" and "=") used to delimit portions of the DSN. To include such characters within a value, encode them in quoted-printable style (e.g., "=20" will be translated into a single space character). Encoding of spaces is also advised. .TP .I e) If the string begins with "ldap:", "ldaps:" or "ldapi:", it is presumed to be a space-separated set of one or more LDAP URLs that identify a set of servers to be queried. The first one should be a full RFC4516 LDAP URL indicating a base DN template and optional scope, filter and attribute names to use in queries. When constructing a DN template or filter, the special tokens "$d" and "$D" are replaced with the key being queried and the key broken into components, separated at "." characters, each component preceded by "dc=" and followed by "," (so "example.com" would become "dc=example,dc=com"). If a data set requires multiple values to be returned, the appropriate attribute names should be given in the correct order to satisfy such requests. .TP .I f) If the string begins with "lua:", it is presumed to refer to a file that contains a Lua script to be executed whenever a query is performed. The key for the query is placed in a global variable called "query", which the called script can then access. The script may return any number of values as required for the type of query being performed. .TP .I g) If the string begins with "memcache:", it is presumed to refer to a memory cache database provided by .B memcached. The remainder of the string is a comma-separated list of hosts to which query attempts should be made, each optionally followed by ":" and a port number; that list must be followed by a slash ("/") character and a string that will be used to prefix queries send to the cache. For example: memcache:localhost,otherhost/keyname This would use either "localhost" or "otherhost" to conduct queries, and all strings sent to the dataset will be prefixed with "keyname:". .TP .I h) If the string contains none of these prefixes but ends with ".db", it is presumed to be a Sleepycat DB as described above (if support for same is compiled in). .TP .I i) If the string contains none of these prefixes but starts with a slash ("/") character, it is presumed to be a flat file as described above. .TP .I j) If the string begins with "csl:", the string is treated as a comma-separated list as described in m) below. .TP .I k) If the string begins with "erlang:", it is presumed to refer to a function called to be made to the specified distributed Erlang node(s). The specification is of the form erlang:node@host[,...]:cookie:module:function where .I node[,...] is a list of comma-separated erlang nodes, .I cookie is the cookie for the known nodes of the distributed Erlang setup, .I module is the name of the Erlang module where the function to be called resides, .I function is the name of the Erlang function to be called. For example, (all in one line): erlang:mynode@myhost,myothernode@myotherhost: .br chocolate:dkim:lookup will join the distributed Erlang setup connecting to either "mynode@myhost" or "myothernode@myotherhost" (connections to nodes are tried in order) using "chocolate" as the cookie, and use the function "dkim:lookup/1" for lookups. .TP .I l) If the string begins with "mdb:", it refers to a directory that contains a memory database, as provided by libmdb from OpenLDAP. .TP .I m) In any other case, the string is presumed to be a comma-separated list. Elements in the list are either simple data elements that are part of the set or, in the case of an entry of the form "x=y", are stored as key-value pairs as described above. .SH OPTIONS .TP .I \-A Automatically re-start on failures. Use with caution; if the filter fails instantly after it starts, this can cause a tight .I fork(2) loop. This can be mitigated using some values in the configuration file to limit restarting. See .I opendkim.conf(5). .TP .I \-b modes Selects operating modes. .I modes is a concatenation of characters that indicate which mode(s) of operation are desired. Valid modes are .I s (signer) and .I v (verifier). The default is .I sv except in test mode (see .I \-t below) in which case the default is .I v. .TP .I \-c canon Selects the canonicalization method(s) to be used when signing messages. When verifying, the message's DKIM-Signature: header specifies the canonicalization method. The recognized values are .I relaxed and .I simple as defined by the DKIM specification. The default is .I simple. The value may include two different canonicalizations separated by a slash ("/") character, in which case the first will be applied to the headers and the second to the body. .TP .I \-d dataset A set of domains whose mail should be signed by this filter. Mail from other domains will be verified rather than being signed. .TP .I \-D Sign subdomains of those listed by the .I \-d option as well as the actual domains. .TP .I \-e name Extracts the value of .I name from the configuration file (if any). .TP .I \-f Normally .I opendkim forks and exits immediately, leaving the service running in the background. This flag suppresses that behaviour so that it runs in the foreground. .TP .I \-F time Specifies a fixed time to use when generating signatures. Ignored unless also used in conjunction with .I \-t (see below). The time must be expressed in the usual UNIX .I time_t (seconds since epoch) format. .TP .I \-k keyfile Gives the location of a PEM-formatted private key to be used for signing all messages. Ignored if a configuration file is referenced that defines a KeyTable. .TP .I \-l Log via calls to .I syslog(3) any interesting activity. .TP .I \-L min[%+] Instructs the verification code to fail messages for which a partial signature was received. There are three possible formats: .I min indicating at least .I min bytes of the message must be signed (or if the message is smaller than .I min then all of it must be signed); .I min% requiring that at least .I min percent of the received message must be signed; and .I min+ meaning there may be no more than .I min bytes of unsigned data appended to the message for it to be considered valid. .TP .I \-n Parse the configuration file and command line arguments, reporting any errors found, and then exit. The exit value will be 0 if the filter would start up without complaint, or non-zero otherwise. .TP .I \-o dataset Specifies a list of headers that should be omitted when generating signatures. If an entry in the list names any header which is mandated by the DKIM specification, the entry is ignored. A set of headers is listed in the DKIM specification as "SHOULD NOT" be signed; the default list for this parameter contains those headers (Return-Path, Received, Comments, Keywords, Bcc, Resent-Bcc and DKIM-Signature). To omit no headers, simply use the string "-" (or any string that will match no headers). .TP .I \-p socketspec Specifies the socket that should be established by the filter to receive connections from .I sendmail(8) in order to provide service. .I socketspec is in one of two forms: .I local:path which creates a UNIX domain socket at the specified .I path, or .I inet:port[@host] or .I inet6:port[@host] which creates a TCP socket on the specified .I port using the requested protocol family. If the .I host is not given as either a hostname or an IP address, the socket will be listening on all interfaces. A literal IP address must be enclosed in square brackets. If neither socket type is specified, .I local is assumed, meaning the parameter is interpreted as a path at which the socket should be created. This parameter is mandatory either here or in the configuration file. .TP .I \-P pidfile Specifies a file into which the filter should write its process ID at startup. .TP .I \-Q Query test mode. The filter will read two lines from standard input, one containing a database description to be opened and one containing a string of the form "q/n" where "q" is the query to be performed and "n" is the number of fields to be retrieved. .TP .I \-r Checks all messages for compliance with RFC5322 header count requirements. Non-compliant messages are rejected. .TP .I \-s selector Defines the name of the selector to be used when signing messages. See the .B DKIM specification for details. .TP .I \-S signalg Selects the signing algorithm to use when generating signatures. Use 'opendkim \-V' to see the list of supported algorithms. The default is .I rsa-sha256 if it is available, otherwise it will be .I rsa-sha1. .TP .I \-t testfiles Evaluates (verifies) one or more RFC5322-formatted message found in .I testfiles and exits. The value of .I testfiles should be a comma-separated list of one or more filenames, one of which may be "-" if the message should be read from standard input. .TP .I \-T secs Sets the DNS timeout in seconds. A value of 0 causes an infinite wait. The default is 5. Ignored if not using an asynchronous resolver package. See also the NOTES section below. .TP .I \-u userid[:group] Attempts to be come the specified .I userid before starting operations. The process will be assigned all of the groups and primary group ID of the named .I userid unless an alternate .I group is specified. See the FILE PERMISSIONS section for more information. .TP .I \-v Increase verbose output during test mode (see .I \-t above). May be specified more than once to request increasing amounts of output. .TP .I \-V Print the version number and supported canonicalization and signature algorithms, and then exit without doing anything else. .TP .I \-W If logging is enabled (see .I \-l above), issues very detailed logging about the logic behind the filter's decision to either sign a message or verify it. The "W" stands for "Why?!" since the logic behind the decision is non-trivial and can be confusing to administrators not familiar with its operation. A description of how the decision is made can be found in the OPERATION section of this document. This causes a large increase in the amount of log data generated for each message, so it should be limited to debugging use and not enabled for general operation. .TP .I \-x configfile Read the named configuration file. See the .I opendkim.conf(5) man page for details. Values in the configuration file are overridden when their equivalents are provided on the command line until a configuration reload occurs. The OPERATION section describes how reloads are triggered. The default is to read a configuration file from .I @SYSCONFDIR@/opendkim.conf if one exists, or otherwise to apply defaults to all values. .TP .I \-X Tolerates configuration file items that have been internally marked as "deprecated". Normally when a configuration file item is removed from the package, it is flagged in this way for at least one full release cycle. The presence of a deprecated configuration file item typically causes the filter to return an error and refuse to start. Setting this flag will allow the filter to start and a warning is logged. In some future release when the item is removed completely, a different error results, and it will not be possible to start the filter. Use of this flag is NOT RECOMMENDED; it could effectively hide a major configuration change with serious security implications. .SH OPERATION A message will be verified unless it conforms to the signing criteria, which are: (1) the domain on the From: address (if present) must be listed by the .I \-d command line switch or the .I Domain configuration file setting, and (2) (a) the client connecting to the MTA must have authenticated, or (b) the client connecting to the MTA must be listed in the file referenced by the .I InternalHosts configuration file setting (or be in the default list for that option), or (c) the client must be connected to a daemon port named by the .I MTAs configuration file setting, or (d) the MTA must have set one or more macros matching the criteria set by the .I MacroList configuration file setting. For (a) above, the test is whether or not the MTA macro "{auth_type}" is set and contains any non-empty value. This means the MTA must pass the value of that macro to the filter before or during the end-of-header (EOH) phase in order for its value to be tested. Check your MTA's configuration documentation for details. For (1) above, other header fields may be selected using the SenderHeaders configuration file setting. See .I opendkim.conf(5) for more information. When signing a message, a .I DKIM-Signature: header will be prepended to the message. The signature is computed using the private key provided. You must be running a version of .I sendmail(8) recent enough to be able to do header prepend operations (8.13.0 or later). When verifying a message, an .I Authentication-Results: header will be prepended to indicate the presence of a signature and whether or not it could be validated against the body of the message using the public key advertised by the sender's nameserver. The value of this header can be used by mail user agents to sort or discard messages that were not signed or could not be verified. Upon receiving SIGUSR1, if the filter was started with a configuration file, it will be re-read and the new values used. Note that any command line overrides provided at startup time will be lost when this is done. Also, the following configuration file values (and their corresponding command line items, if any) are not reloaded through this process: AutoRestart (\-A), AutoRestartCount, AutoRestartRate, Background, MilterDebug, PidFile (\-P), POPDBFile, Quarantine (\-q), QueryCache, Socket (\-p), StrictTestMode, TestPublicKeys, UMask, UserID (\-u). The filter does not automatically check the configuration file for changes and reload. .SH MTA MACROS .B opendkim makes use of three MTA-provided macros, plus any demanded by configuration. The basic three are: "i" (the envelope ID, also known as the job ID or the queue ID), which is used for logging; "daemon_name" (the symbolic name given to the MTA instance that accepted the connection), which is used when performing tests against any "MTAs" setting used; and "auth_type", which is used to determine whether or not the SMTP client authenticated to the MTA. If the MTA does not provide them to .B opendkim then it is not able to apply their corresponding tests or do useful logging. Consult your MTA documentation to determine how to adjust your its configuration if some or all of these are not available. .SH FILE PERMISSIONS When the filter is started as the superuser and the UserID (\-u) setting is used, the filter gives up its root privileges by changing to the specified user after the following steps are taken: (1) the configuration file (if any) is loaded; (2) if the KeyFile (\-k) setting is used, that key is loaded into memory; (3) all data sets in the configuration file are opened, and those that are based on flat files are also read into memory; and (4) if ChangeRootDirectory is set, the process root is changed to that directory. This means on configuration reload, the filter will not be accessing these files or the configuration file as the superuser (and possibly from a different root), and any key files referenced by the KeyTable will also be accessed by the new user. Thus, keys referenced by the KeyTable must always be accessible for read by the unprivileged user. Also, run-time reloads are not possible if any of the other files will not be readable by the unprivileged user. .SH ENVIRONMENT The following environment variable(s) can be used to adjust the behaviour of this filter: .TP .I DKIM_TMPDIR The directory to use when creating temporary files. The default is .I /tmp. .SH NOTES When using DNS timeouts (see the .I \-T option above), be sure not to use a timeout that is larger than the timeout being used for interaction between .I sendmail and the filter. Otherwise, the MTA could abort a message while waiting for a reply from the filter, which in turn is still waiting for a DNS reply. The POP authentication database is expected to be a Sleepycat DB file (formerly known as a Berkeley DB) in hash format with keys containing the IP address in text form without a terminating NULL. The values of these records are not checked; only the existence of such records is of interest. The filter will attempt to establish a shared lock on the database before reading from it, so any programs which write to the database should keep their lock use to a minimum or else this filter will appear to hang while waiting for the lock operation to complete. Features that involve specification of IPv4 addresses or CIDR blocks will use the .I inet_addr(3) function to parse that information. Users should be familiar with the way that function handles the non-trivial cases (for example, "192.0.2/24" and "192.0.2.0/24" are not the same thing). .SH EXIT STATUS Filter exit status codes are selected according to .I sysexits(3). .SH HISTORY DKIM is an amalgam of Yahoo!'s .B DomainKeys proposal, and Cisco's .B Internet Identified Mail (IIM) proposal. .SH VERSION This man page covers version @VERSION@ of .I opendkim. .SH COPYRIGHT Copyright (c) 2005-2008, Sendmail, Inc. and its suppliers. All rights reserved. Copyright (c) 2009-2013, 2015, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim.conf(5), sendmail(8) .P Sendmail Operations Guide .P RFC5321 - Simple Mail Transfer Protocol .P RFC5322 - Internet Messages .P RFC5451 - Message Header Field for Indicating Message Authentication Status .P RFC6008 - Authentication-Results Registration for Differentiating among Cryptographic Results .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.c000066400000000000000000013425121337314105200222450ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, 2018, The Trusted Domain Project. ** All rights reserved. */ #include "build-config.h" #ifndef _POSIX_PTHREAD_SEMANTICS # define _POSIX_PTHREAD_SEMANTICS #endif /* ! _POSIX_PTHREAD_SEMANTICS */ /* system includes */ #include #include #include #include #include #ifdef HAVE_ISO_LIMITS_ISO_H # include #endif /* HAVE_ISO_LIMITS_ISO_H */ #ifdef HAVE_LIMITS_H # include #endif /* HAVE_LIMITS_H */ #ifdef __linux__ # include #endif /* __linux__ */ #ifdef USE_LUA # include # include #endif /* USE_LUA */ #ifdef AF_INET6 # include #endif /* AF_INET6 */ #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_GNUTLS # include # include #else /* USE_GNUTLS */ # include # include #endif /* USE_GNUTLS */ #ifndef SHA_DIGEST_LENGTH # define SHA_DIGEST_LENGTH 20 #endif /* ! SHA_DIGEST_LENGTH */ #ifdef HAVE_PATHS_H # include #endif /* HAVE_PATHS_H */ #ifndef _PATH_DEVNULL # define _PATH_DEVNULL "/dev/null" #endif /* ! _PATH_DEVNULL */ /* libmilter includes */ #include "libmilter/mfapi.h" #ifdef USE_LUA /* LUA includes */ # include #endif /* USE_LUA */ #ifdef _FFR_RBL /* librbl includes */ # include #endif /* _FFR_RBL */ /* libopendkim includes */ #include "dkim.h" #ifdef _FFR_VBR # include "vbr.h" #endif /* _FFR_VBR */ /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ #ifdef _FFR_REPUTATION /* reputation includes */ # include #endif /* _FFR_REPUTATION */ #ifdef _FFR_REPRRD # include #endif /* _FFR_REPRRD */ /* opendkim includes */ #include "config.h" #ifdef _FFR_RATE_LIMIT # include "flowrate.h" #endif /* _FFR_RATE_LIMIT */ #include "opendkim-db.h" #include "opendkim-config.h" #include "opendkim-crypto.h" #include "opendkim.h" #include "opendkim-ar.h" #include "opendkim-arf.h" #include "opendkim-dns.h" #ifdef USE_LUA # include "opendkim-lua.h" #endif /* USE_LUA */ #include "util.h" #include "test.h" #ifdef _FFR_STATS # include "stats.h" #endif /* _FFR_STATS */ #ifdef _FFR_REPUTATION # include "reputation.h" #endif /* _FFR_REPUTATION */ /* macros */ #define CMDLINEOPTS "Ab:c:d:De:fF:k:lL:no:p:P:Qrs:S:t:T:u:vVWx:X?" #ifndef MIN # define MIN(x,y) ((x) < (y) ? (x) : (y)) #endif /* ! MIN */ #define DKIMF_MILTER_ACCEPT 0 #define DKIMF_MILTER_REJECT 1 #define DKIMF_MILTER_TEMPFAIL 2 #define DKIMF_MILTER_DISCARD 3 #define DKIMF_MILTER_QUARANTINE 4 /* ** ADDRLIST -- address list */ struct addrlist { char * a_addr; /* address */ struct addrlist * a_next; /* next record */ }; /* ** HANDLING -- message handling requests */ struct handling { int hndl_nosig; /* no signature */ int hndl_badsig; /* bad signature */ int hndl_nokey; /* no key in DNS */ int hndl_dnserr; /* DNS error */ int hndl_internal; /* internal error */ #if defined(_FFR_REPUTATION) || defined(_FFR_REPRRD) int hndl_reperr; /* reputation error */ #endif /* _FFR_REPUTATION || _FFR_REPRRD */ int hndl_security; /* security concerns */ int hndl_siggen; /* sig generation errors */ }; struct handling defaults = { DKIMF_MILTER_ACCEPT, /* nosig */ DKIMF_MILTER_ACCEPT, /* badsig */ DKIMF_MILTER_ACCEPT, /* nokey */ DKIMF_MILTER_TEMPFAIL, /* dnserr */ DKIMF_MILTER_TEMPFAIL, /* internal */ #ifdef _FFR_REPUTATION DKIMF_MILTER_ACCEPT, /* reperror */ #endif /* _FFR_REPUTATION */ DKIMF_MILTER_TEMPFAIL, /* security */ DKIMF_MILTER_REJECT /* siggen */ }; /* ** LUA_GLOBAL -- linked list of Lua globals */ struct lua_global { int lg_type; char * lg_name; void * lg_value; struct lua_global * lg_next; }; /* ** CONFIG -- configuration data */ struct dkimf_config { _Bool conf_disablecryptoinit; /* initialize SSL libs? */ #if defined(USE_LDAP) || defined(USE_ODBX) _Bool conf_softstart; /* do LDAP/SQL soft starts */ #endif /* defined(USE_LDAP) || defined(USE_ODBX) */ #ifdef _FFR_LUA_ONLY_SIGNING _Bool conf_luasigning; /* signing via Lua only */ #endif /* _FFR_LUA_ONLY_SIGNING */ _Bool conf_weaksyntax; /* do weaker syntax checking */ _Bool conf_passmalformed; /* pass malformed messages */ _Bool conf_logresults; /* log all results */ _Bool conf_dnsconnect; /* request TCP mode from DNS */ _Bool conf_capture; /* capture unknown errors */ _Bool conf_restrace; /* resolver tracing? */ _Bool conf_acceptdk; /* accept DK keys? */ _Bool conf_addswhdr; /* add identifying header? */ _Bool conf_blen; /* use "l=" when signing */ _Bool conf_ztags; /* use "z=" when signing */ _Bool conf_alwaysaddar; /* always add Auth-Results:? */ _Bool conf_reqreports; /* request reports */ _Bool conf_sendreports; /* signature failure reports */ _Bool conf_reqhdrs; /* required header checks */ _Bool conf_authservidwithjobid; /* use jobids in A-R headers */ _Bool conf_subdomains; /* sign subdomains */ _Bool conf_remsigs; /* remove current signatures? */ _Bool conf_remarall; /* remove all matching ARs? */ _Bool conf_keepar; /* keep our ARs? */ _Bool conf_dolog; /* syslog interesting stuff? */ _Bool conf_dolog_success; /* syslog successes too? */ _Bool conf_milterv2; /* using milter v2? */ _Bool conf_fixcrlf; /* fix bare CRs and LFs? */ _Bool conf_logwhy; /* log mode decision logic */ _Bool conf_allowsha1only; /* allow rsa-sha1 verifying */ _Bool conf_stricthdrs; /* strict header checks */ _Bool conf_keeptmpfiles; /* keep temporary files */ _Bool conf_multisig; /* multiple signatures */ _Bool conf_enablecores; /* enable coredumps */ _Bool conf_noheaderb; /* suppress "header.b" */ _Bool conf_singleauthres; /* single Auth-Results */ _Bool conf_safekeys; /* check key permissions */ #ifdef _FFR_RESIGN _Bool conf_resignall; /* resign unverified mail */ #endif /* _FFR_RESIGN */ #ifdef USE_LDAP _Bool conf_ldap_usetls; /* LDAP TLS */ #endif /* USE_LDAP */ #ifdef _FFR_VBR _Bool conf_vbr_purge; /* purge X-VBR-* fields */ _Bool conf_vbr_trustedonly; /* trusted certifiers only */ #endif /* _FFR_VBR */ #if defined(_FFR_REPUTATION) || defined(_FFR_REPRRD) _Bool conf_reptest; /* reputation test mode */ _Bool conf_repverbose; /* verbose reputation logs */ #endif /* _FFR_REPUTATION || _FFR_REPRRD */ unsigned int conf_mode; /* operating mode */ unsigned int conf_refcnt; /* reference count */ unsigned int conf_dnstimeout; /* DNS timeout */ unsigned int conf_maxhdrsz; /* max header bytes */ unsigned int conf_maxverify; /* max sigs to verify */ unsigned int conf_minkeybits; /* min key size (bits) */ #ifdef _FFR_REPUTATION unsigned int conf_repfactor; /* reputation factor */ unsigned int conf_repminimum; /* reputation minimum */ unsigned int conf_repcachettl; /* reputation cache TTL */ unsigned int conf_reptimeout; /* reputation query timeout */ #endif /* _FFR_REPUTATION */ unsigned int conf_boguskey; /* bogus key action */ unsigned int conf_unprotectedkey; /* unprotected key action */ #ifdef _FFR_RATE_LIMIT unsigned int conf_flowdatattl; /* flow data TTL */ unsigned int conf_flowfactor; /* flow factor */ #endif /* _FFR_RATE_LIMIT */ int conf_clockdrift; /* tolerable clock drift */ int conf_sigmintype; /* signature minimum type */ size_t conf_sigmin; /* signature minimum */ size_t conf_keylen; /* size of secret key */ #ifdef USE_LUA size_t conf_screenfuncsz; /* screening function size */ size_t conf_setupfuncsz; /* setup function size */ # ifdef _FFR_STATS size_t conf_statsfuncsz; /* stats function size */ # endif /* _FFR_STATS */ size_t conf_finalfuncsz; /* final function size */ #endif /* USE_LUA */ ssize_t conf_signbytes; /* bytes to sign */ dkim_canon_t conf_hdrcanon; /* canon. method for headers */ dkim_canon_t conf_bodycanon; /* canon. method for body */ unsigned long conf_sigttl; /* signature TTLs */ dkim_alg_t conf_signalg; /* signing algorithm */ struct config * conf_data; /* configuration data */ #ifdef HAVE_CURL_EASY_STRERROR char * conf_smtpuri; /* outgoing mail URI */ #endif /* HAVE_CURL_EASY_STRERROR */ char * conf_authservid; /* authserv-id */ char * conf_keyfile; /* key file for single key */ char * conf_keytable; /* key table */ char * conf_signtable; /* signing table */ char * conf_peerfile; /* peer file */ char * conf_internalfile; /* internal hosts file */ char * conf_externalfile; /* external hosts file */ char * conf_exemptfile; /* exempt domains file */ char * conf_tmpdir; /* temp directory */ char * conf_omitlist; /* omit header list */ char * conf_domlist; /* signing domain list */ char * conf_signalgstr; /* signature algorithm string */ char * conf_modestr; /* mode string */ char * conf_canonstr; /* canonicalization(s) string */ char * conf_siglimit; /* signing limits */ char * conf_chroot; /* chroot(2) directory */ char * conf_selectcanonhdr; /* canon select header name */ u_char * conf_selector; /* key selector */ #ifdef _FFR_CONDITIONAL char * conf_conditional; /* conditional signing */ #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_DEFAULT_SENDER char * conf_defsender; /* default sender address */ #endif /* _FFR_DEFAULT_SENDER */ #ifdef _FFR_RESIGN char * conf_resign; /* resign mail to */ #endif /* _FFR_RESIGN */ #ifdef _FFR_SENDER_MACRO char * conf_sendermacro; /* macro containing sender */ #endif /* _FFR_SENDER_MACRO */ char * conf_testdnsdata; /* test DNS data */ #ifdef _FFR_IDENTITY_HEADER char * conf_identityhdr; /* identity header */ _Bool conf_rmidentityhdr; /* remove identity header */ #endif /* _FFR_IDENTITY_HEADER */ char * conf_diagdir; /* diagnostics directory */ #ifdef _FFR_STATS char * conf_statspath; /* path for stats file */ char * conf_reporthost; /* reporter name */ char * conf_reportprefix; /* stats data prefix */ #endif /* _FFR_STATS */ char * conf_reportaddr; /* report sender address */ char * conf_reportaddrbcc; /* report repcipient address as bcc */ char * conf_mtacommand; /* MTA command (reports) */ char * conf_redirect; /* redirect failures to */ #ifdef USE_LDAP char * conf_ldap_timeout; /* LDAP timeout */ char * conf_ldap_kaidle; /* LDAP keepalive idle */ char * conf_ldap_kaprobes; /* LDAP keepalive probes */ char * conf_ldap_kainterval; /* LDAP keepalive interval */ char * conf_ldap_binduser; /* LDAP bind user */ char * conf_ldap_bindpw; /* LDAP bind password */ char * conf_ldap_authmech; /* LDAP auth mechanism */ # ifdef USE_SASL char * conf_ldap_authname; /* LDAP auth name */ char * conf_ldap_authuser; /* LDAP auth user */ char * conf_ldap_authrealm; /* LDAP auth realm */ # endif /* USE_SASL */ #endif /* USE_LDAP */ #ifdef USE_LUA char * conf_screenscript; /* Lua script: screening */ void * conf_screenfunc; /* Lua function: screening */ char * conf_setupscript; /* Lua script: setup */ void * conf_setupfunc; /* Lua function: setup */ # ifdef _FFR_STATSEXT char * conf_statsscript; /* Lua script: stats */ void * conf_statsfunc; /* Lua function: stats */ # endif /* _FFR_STATSEXT */ char * conf_finalscript; /* Lua script: final */ void * conf_finalfunc; /* Lua function: final */ #endif /* USE_LUA */ #ifdef _FFR_REPLACE_RULES char * conf_rephdrs; /* replacement headers */ struct replace * conf_replist; /* replacement list */ DKIMF_DB conf_rephdrsdb; /* replacement headers (DB) */ #endif /* _FFR_REPLACE_RULES */ dkim_sigkey_t conf_seckey; /* secret key data */ char * conf_nslist; /* replacement NS list */ char * conf_trustanchorpath; /* trust anchor file */ char * conf_resolverconfig; /* resolver config file */ #ifdef _FFR_VBR char * conf_vbr_deftype; /* default VBR type */ char * conf_vbr_defcert; /* default VBR certifiers */ DKIMF_DB conf_vbr_trusteddb; /* trusted certifiers (DB) */ u_char ** conf_vbr_trusted; /* trusted certifiers */ #endif /* _FFR_VBR */ DKIMF_DB conf_testdnsdb; /* test TXT records */ DKIMF_DB conf_bldb; /* l= recipients (DB) */ DKIMF_DB conf_domainsdb; /* domains to sign (DB) */ DKIMF_DB conf_omithdrdb; /* headers to omit (DB) */ char ** conf_omithdrs; /* headers to omit (array) */ DKIMF_DB conf_signhdrsdb; /* headers to sign (DB) */ char ** conf_signhdrs; /* headers to sign (array) */ DKIMF_DB conf_senderhdrsdb; /* sender headers (DB) */ char ** conf_senderhdrs; /* sender headers (array) */ DKIMF_DB conf_mtasdb; /* MTA ports to sign (DB) */ char ** conf_mtas; /* MTA ports to sign (array) */ DKIMF_DB conf_remardb; /* A-R removal list (DB) */ char ** conf_remar; /* A-R removal list (array) */ DKIMF_DB conf_mbsdb; /* must-be-signed hdrs (DB) */ char ** conf_mbs; /* must-be-signed (array) */ DKIMF_DB conf_oversigndb; /* fields to over-sign (DB) */ char ** conf_oversignhdrs; /* " " " (array) */ DKIMF_DB conf_dontsigntodb; /* don't-sign-to addrs (DB) */ #ifdef _FFR_ATPS DKIMF_DB conf_atpsdb; /* ATPS domains */ char * conf_atpshash; /* ATPS hash algorithm */ #endif /* _FFR_ATPS */ DKIMF_DB conf_thirdpartydb; /* trustsigsfrom DB */ DKIMF_DB conf_macrosdb; /* macros/values (DB) */ char ** conf_macros; /* macros/values to check */ regex_t ** conf_nosignpats; /* do-not-sign patterns */ DKIMF_DB conf_peerdb; /* DB of "peers" */ DKIMF_DB conf_internal; /* DB of "internal" hosts */ DKIMF_DB conf_exignore; /* "external ignore" host DB */ DKIMF_DB conf_exemptdb; /* exempt domains DB */ DKIMF_DB conf_keytabledb; /* key table DB */ DKIMF_DB conf_signtabledb; /* signing table DB */ #ifdef _FFR_STATS DKIMF_DB conf_anondb; /* anonymized domains DB */ #endif /* _FFR_STATS */ #ifdef _FFR_RESIGN DKIMF_DB conf_resigndb; /* resigning addresses */ #endif /* _FFR_RESIGN */ #ifdef _FFR_RATE_LIMIT DKIMF_DB conf_ratelimitdb; /* domain rate limits */ DKIMF_DB conf_flowdatadb; /* domain flow data */ #endif /* _FFR_RATE_LIMIT */ #ifdef _FFR_CONDITIONAL DKIMF_DB conf_conditionaldb; /* conditional signatures DB */ #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_REPUTATION char * conf_repratios; /* reputed ratios */ DKIMF_DB conf_repratiosdb; /* reputed ratios DB */ char * conf_replimits; /* reputed limits */ DKIMF_DB conf_replimitsdb; /* reputed limits DB */ char * conf_replimitmods; /* reputed limit modifiers */ DKIMF_DB conf_replimitmodsdb; /* reputed limit mods DB */ char * conf_replowtime; /* reputed low timers */ DKIMF_DB conf_replowtimedb; /* reputed low timers DB */ DKIMF_REP conf_rep; /* reputation subsystem */ char * conf_repcache; /* reputation cache DB */ char * conf_repdups; /* reputation duplicates DB */ char * conf_repspamcheck; /* reputation spam RE string */ regex_t conf_repspamre; /* reputation spam RE */ #endif /* _FFR_REPUTATION */ #ifdef _FFR_REPRRD REPRRD conf_reprrd; /* reputation RRD handle */ #endif /* _FFR_REPRRD */ DKIM_LIB * conf_libopendkim; /* DKIM library handle */ struct handling conf_handling; /* message handling */ }; /* ** MSGCTX -- message context, containing transaction-specific data */ typedef struct msgctx * msgctx; struct msgctx { _Bool mctx_internal; /* internal source? */ _Bool mctx_bldbdone; /* BodyLengthDB applied? */ _Bool mctx_eom; /* in EOM? (enables progress) */ _Bool mctx_addheader; /* Authentication-Results: */ _Bool mctx_headeronly; /* in EOM, only add headers */ _Bool mctx_ltag; /* sign with l= tag? */ _Bool mctx_capture; /* capture message? */ _Bool mctx_susp; /* suspicious message? */ #ifdef _FFR_RESIGN _Bool mctx_resign; /* arrange to re-sign */ #endif /* _FFR_RESIGN */ #ifdef _FFR_VBR _Bool mctx_vbrpurge; /* purge X-VBR-* headers */ #endif /* _FFR_VBR */ #ifdef _FFR_REPUTATION _Bool mctx_spam; /* is spam? */ #endif /* _FFR_REPUTATION */ #ifdef _FFR_ATPS int mctx_atps; /* ATPS */ #endif /* _FFR_ATPS */ #ifdef USE_LUA int mctx_mresult; /* SMFI status code */ #endif /* USE_LUA */ int mctx_status; /* status to report back */ dkim_canon_t mctx_hdrcanon; /* header canonicalization */ dkim_canon_t mctx_bodycanon; /* body canonicalization */ dkim_alg_t mctx_signalg; /* signature algorithm */ #ifdef USE_UNBOUND int mctx_dnssec_key; /* DNSSEC results for key */ #endif /* USE_UNBOUND */ int mctx_queryalg; /* query algorithm */ int mctx_hdrbytes; /* header space allocated */ struct dkimf_dstring * mctx_tmpstr; /* temporary string */ u_char * mctx_jobid; /* job ID */ u_char * mctx_laddr; /* address triggering l= */ DKIM * mctx_dkimv; /* verification handle */ #ifdef _FFR_VBR VBR * mctx_vbr; /* VBR handle */ char * mctx_vbrinfo; /* VBR-Info header field */ #endif /* _FFR_VBR */ struct Header * mctx_hqhead; /* header queue head */ struct Header * mctx_hqtail; /* header queue tail */ struct signreq * mctx_srhead; /* signature request head */ struct signreq * mctx_srtail; /* signature request tail */ struct addrlist * mctx_rcptlist; /* recipient list */ #ifdef _FFR_STATSEXT struct statsext * mctx_statsext; /* extension stats list */ #endif /* _FFR_STATSEXT */ struct lua_global * mctx_luaglobalh; /* Lua global list */ struct lua_global * mctx_luaglobalt; /* Lua global list */ #ifdef _FFR_REPUTATION # ifdef USE_GNUTLS gnutls_hash_hd_t mctx_hash; /* hash, for dup detection */ # else /* USE_GNUTLS */ SHA_CTX mctx_hash; /* hash, for dup detection */ # endif /* USE_GNUTLS */ #endif /* _FFR_REPUTATION */ unsigned char mctx_envfrom[MAXADDRESS + 1]; /* envelope sender */ unsigned char mctx_domain[DKIM_MAXHOSTNAMELEN + 1]; /* primary domain */ unsigned char mctx_dkimar[DKIM_MAXHEADER + 1]; /* DKIM Auth-Results content */ }; /* ** CONNCTX -- connection context, containing thread-specific data */ typedef struct connctx * connctx; struct connctx { _Bool cctx_milterv2; /* milter v2 available */ _Bool cctx_noleadspc; /* no leading spaces */ char cctx_host[DKIM_MAXHOSTNAMELEN + 1]; /* hostname */ struct sockaddr_storage cctx_ip; /* IP info */ struct dkimf_config * cctx_config; /* configuration in use */ struct msgctx * cctx_msg; /* message context */ }; /* ** LOOKUP -- lookup table */ struct lookup { char * str; int code; }; #define HNDL_DEFAULT 0 #define HNDL_NOSIGNATURE 1 #define HNDL_BADSIGNATURE 2 #define HNDL_DNSERROR 3 #define HNDL_INTERNAL 4 #define HNDL_SECURITY 5 #define HNDL_NOKEY 6 #define HNDL_POLICYERROR 7 #define HNDL_REPERROR 8 #define HNDL_SIGGEN 9 #define DKIMF_MODE_SIGNER 0x01 #define DKIMF_MODE_VERIFIER 0x02 #define DKIMF_MODE_DEFAULT (DKIMF_MODE_SIGNER|DKIMF_MODE_VERIFIER) #define DKIMF_STATUS_GOOD 0 #define DKIMF_STATUS_BAD 1 #define DKIMF_STATUS_NOKEY 2 #define DKIMF_STATUS_REVOKED 3 #define DKIMF_STATUS_NOSIGNATURE 4 #define DKIMF_STATUS_BADFORMAT 5 #define DKIMF_STATUS_PARTIAL 6 #define DKIMF_STATUS_VERIFYERR 7 #define DKIMF_STATUS_UNKNOWN 8 #define SIGMIN_BYTES 0 #define SIGMIN_PERCENT 1 #define SIGMIN_MAXADD 2 #if defined(_FFR_REPUTATION) || defined(_FFR_REPRRD) # define REPDENYSMTP "450" # define REPDENYESC "4.7.1" # define REPDENYTXT "Message deferred for policy reasons" #endif /* _FFR_REPUTATION || _FFR_REPRRD */ #define DELIMITER "\001" struct lookup dkimf_params[] = { { "badsignature", HNDL_BADSIGNATURE }, { "default", HNDL_DEFAULT }, { "dnserror", HNDL_DNSERROR }, { "internalerror", HNDL_INTERNAL }, { "keynotfound", HNDL_NOKEY }, { "nosignature", HNDL_NOSIGNATURE }, #ifdef _FFR_REPUTATION { "reputationerror", HNDL_REPERROR }, #endif /* _FFR_REPUTATION */ { "security", HNDL_SECURITY }, { "signatureerror", HNDL_SIGGEN }, { NULL, -1 }, }; struct lookup dkimf_values[] = { { "a", DKIMF_MILTER_ACCEPT }, { "accept", DKIMF_MILTER_ACCEPT }, { "d", DKIMF_MILTER_DISCARD }, { "discard", DKIMF_MILTER_DISCARD }, #ifdef SMFIF_QUARANTINE { "q", DKIMF_MILTER_QUARANTINE }, { "quarantine", DKIMF_MILTER_QUARANTINE }, #endif /* SMFIF_QUARANTINE */ { "r", DKIMF_MILTER_REJECT }, { "reject", DKIMF_MILTER_REJECT }, { "t", DKIMF_MILTER_TEMPFAIL }, { "tempfail", DKIMF_MILTER_TEMPFAIL }, { NULL, -1 }, }; struct lookup dkimf_canon[] = { { "relaxed", DKIM_CANON_RELAXED }, { "simple", DKIM_CANON_SIMPLE }, { NULL, -1 }, }; struct lookup dkimf_sign[] = { { "rsa-sha1", DKIM_SIGN_RSASHA1 }, { "rsa-sha256", DKIM_SIGN_RSASHA256 }, { "ed25519-sha256", DKIM_SIGN_ED25519SHA256 }, { NULL, -1 }, }; struct lookup dkimf_atpshash[] = { #ifdef HAVE_SHA256 { "sha256", 1 }, #endif /* HAVE_SHA256 */ { "sha1", 1 }, { "none", 1 }, { NULL, -1 }, }; struct lookup log_facilities[] = { { "auth", LOG_AUTH }, { "cron", LOG_CRON }, { "daemon", LOG_DAEMON }, { "kern", LOG_KERN }, { "lpr", LOG_LPR }, { "mail", LOG_MAIL }, { "news", LOG_NEWS }, { "security", LOG_AUTH }, /* DEPRECATED */ { "syslog", LOG_SYSLOG }, { "user", LOG_USER }, { "uucp", LOG_UUCP }, { "local0", LOG_LOCAL0 }, { "local1", LOG_LOCAL1 }, { "local2", LOG_LOCAL2 }, { "local3", LOG_LOCAL3 }, { "local4", LOG_LOCAL4 }, { "local5", LOG_LOCAL5 }, { "local6", LOG_LOCAL6 }, { "local7", LOG_LOCAL7 }, { NULL, -1 } }; # define DKIMF_KEYACTIONS_NONE 0 # define DKIMF_KEYACTIONS_NEUTRAL 1 # define DKIMF_KEYACTIONS_FAIL 2 struct lookup dkimf_keyactions[] = { { "none", DKIMF_KEYACTIONS_NONE }, { "neutral", DKIMF_KEYACTIONS_NEUTRAL }, { "fail", DKIMF_KEYACTIONS_FAIL }, { NULL, -1 }, }; struct lookup dkimf_statusstrings[] = { { "no error", DKIMF_STATUS_GOOD }, { "bad signature", DKIMF_STATUS_BAD }, { "key retrieval failed", DKIMF_STATUS_NOKEY }, { "key revoked", DKIMF_STATUS_REVOKED }, { "no signature", DKIMF_STATUS_NOSIGNATURE }, { "bad message/signature format", DKIMF_STATUS_BADFORMAT }, { "invalid partial signature", DKIMF_STATUS_PARTIAL }, { "verification error", DKIMF_STATUS_VERIFYERR }, { "unknown error", DKIMF_STATUS_UNKNOWN }, { NULL, -1 } }; /* PROTOTYPES */ #ifdef LEAK_TRACKING void dkimf_debug_free __P((void *, char *, int)); void *dkim_debug_malloc __P((size_t, char *, int)); void *dkim_debug_realloc __P((void *, size_t, char *, int)); # define free(x) dkimf_debug_free((x), __FILE__, __LINE__) # define malloc(x) dkimf_debug_malloc((x), __FILE__, __LINE__) # define realloc(x,y) dkimf_debug_realloc((x), (y), __FILE__, __LINE__) #endif /* LEAK_TRACKING */ sfsistat mlfi_abort __P((SMFICTX *)); sfsistat mlfi_body __P((SMFICTX *, u_char *, size_t)); sfsistat mlfi_close __P((SMFICTX *)); sfsistat mlfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *)); sfsistat mlfi_envfrom __P((SMFICTX *, char **)); sfsistat mlfi_envrcpt __P((SMFICTX *, char **)); sfsistat mlfi_eoh __P((SMFICTX *)); sfsistat mlfi_eom __P((SMFICTX *)); sfsistat mlfi_header __P((SMFICTX *, char *, char *)); sfsistat mlfi_negotiate __P((SMFICTX *, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long *, unsigned long *, unsigned long *, unsigned long *)); static int dkimf_add_signrequest __P((struct msgctx *, DKIMF_DB, char *, char *, ssize_t)); sfsistat dkimf_addheader __P((SMFICTX *, char *, char *)); sfsistat dkimf_addrcpt __P((SMFICTX *, char *)); static int dkimf_apply_signtable __P((struct msgctx *, DKIMF_DB, DKIMF_DB, unsigned char *, unsigned char *, char *, size_t, _Bool)); sfsistat dkimf_chgheader __P((SMFICTX *, char *, int, char *)); static void dkimf_cleanup __P((SMFICTX *)); static void dkimf_config_reload __P((void)); sfsistat dkimf_delrcpt __P((SMFICTX *, char *)); static Header dkimf_findheader __P((msgctx, char *, int)); void *dkimf_getpriv __P((SMFICTX *)); char *dkimf_getsymval __P((SMFICTX *, char *)); sfsistat dkimf_insheader __P((SMFICTX *, int, char *, char *)); sfsistat dkimf_quarantine __P((SMFICTX *, char *)); void dkimf_sendprogress __P((const void *)); sfsistat dkimf_setpriv __P((SMFICTX *, void *)); sfsistat dkimf_setreply __P((SMFICTX *, char *, char *, char *)); static void dkimf_sigreport __P((connctx, struct dkimf_config *, char *)); /* GLOBALS */ _Bool dolog; /* logging? (exported) */ _Bool reload; /* reload requested */ _Bool no_i_whine; /* noted ${i} is undefined */ _Bool testmode; /* test mode */ _Bool allowdeprecated; /* allow deprecated config values */ #ifdef QUERY_CACHE _Bool querycache; /* local query cache */ #endif /* QUERY_CACHE */ _Bool die; /* global "die" flag */ int diesig; /* signal to distribute */ #ifdef QUERY_CACHE time_t cache_lastlog; /* last cache stats logged */ #endif /* QUERY_CACHE */ char *progname; /* program name */ char *sock; /* listening socket */ char *conffile; /* configuration file */ struct dkimf_config *curconf; /* current configuration */ #ifdef POPAUTH DKIMF_DB popdb; /* POP auth DB */ #endif /* POPAUTH */ char reportcmd[BUFRSZ + 1]; /* reporting command */ char reportaddr[MAXADDRESS + 1]; /* reporting address */ char myhostname[DKIM_MAXHOSTNAMELEN + 1]; /* hostname */ pthread_mutex_t conf_lock; /* config lock */ pthread_mutex_t pwdb_lock; /* passwd/group lock */ /* Other useful definitions */ #define CRLF "\r\n" /* CRLF */ /* MACROS */ #define JOBID(x) ((x) == NULL ? JOBIDUNKNOWN : (char *) (x)) #define TRYFREE(x) do { \ if ((x) != NULL) \ { \ free(x); \ (x) = NULL; \ } \ } while (0) #define DKIMF_EOHMACROS "i {daemon_name} {auth_type}" /* ** ================================================================== ** BEGIN private section */ #ifndef HAVE_SMFI_INSHEADER /* ** SMFI_INSHEADER -- stub for smfi_insheader() which didn't exist before ** sendmail 8.13.0 ** ** Parameters: ** ctx -- milter context ** idx -- insertion index ** hname -- header name ** hvalue -- header value ** ** Return value: ** An sfsistat. */ sfsistat smfi_insheader(SMFICTX *ctx, int idx, char *hname, char *hvalue) { assert(ctx != NULL); assert(hname != NULL); assert(hvalue != NULL); return smfi_addheader(ctx, hname, hvalue); } #endif /* ! HAVE_SMFI_INSHEADER */ /* ** DKIMF_GETPRIV -- wrapper for smfi_getpriv() ** ** Parameters: ** ctx -- milter (or test) context ** ** Return value: ** The stored private pointer, or NULL. */ void * dkimf_getpriv(SMFICTX *ctx) { assert(ctx != NULL); if (testmode) return dkimf_test_getpriv((void *) ctx); else return smfi_getpriv(ctx); } /* ** DKIMF_SETPRIV -- wrapper for smfi_setpriv() ** ** Parameters: ** ctx -- milter (or test) context ** ** Return value: ** An sfsistat. */ sfsistat dkimf_setpriv(SMFICTX *ctx, void *ptr) { assert(ctx != NULL); if (testmode) return dkimf_test_setpriv((void *) ctx, ptr); else return smfi_setpriv(ctx, ptr); } /* ** DKIMF_INSHEADER -- wrapper for smfi_insheader() ** ** Parameters: ** ctx -- milter (or test) context ** idx -- index at which to insert ** hname -- header name ** hvalue -- header value ** ** Return value: ** An sfsistat. */ sfsistat dkimf_insheader(SMFICTX *ctx, int idx, char *hname, char *hvalue) { assert(ctx != NULL); assert(hname != NULL); assert(hvalue != NULL); if (testmode) return dkimf_test_insheader(ctx, idx, hname, hvalue); else #ifdef HAVE_SMFI_INSHEADER return smfi_insheader(ctx, idx, hname, hvalue); #else /* HAVE_SMFI_INSHEADER */ return smfi_addheader(ctx, hname, hvalue); #endif /* HAVE_SMFI_INSHEADER */ } /* ** DKIMF_CHGHEADER -- wrapper for smfi_chgheader() ** ** Parameters: ** ctx -- milter (or test) context ** hname -- header name ** idx -- index of header to be changed ** hvalue -- header value ** ** Return value: ** An sfsistat. */ sfsistat dkimf_chgheader(SMFICTX *ctx, char *hname, int idx, char *hvalue) { assert(ctx != NULL); assert(hname != NULL); if (testmode) return dkimf_test_chgheader(ctx, hname, idx, hvalue); else return smfi_chgheader(ctx, hname, idx, hvalue); } /* ** DKIMF_QUARANTINE -- wrapper for smfi_quarantine() ** ** Parameters: ** ctx -- milter (or test) context ** reason -- quarantine reason ** ** Return value: ** An sfsistat. */ sfsistat dkimf_quarantine(SMFICTX *ctx, char *reason) { assert(ctx != NULL); if (testmode) return dkimf_test_quarantine(ctx, reason); #ifdef SMFIF_QUARANTINE else return smfi_quarantine(ctx, reason); #endif /* SMFIF_QUARANTINE */ } /* ** DKIMF_ADDHEADER -- wrapper for smfi_addheader() ** ** Parameters: ** ctx -- milter (or test) context ** hname -- header name ** hvalue -- header value ** ** Return value: ** An sfsistat. */ sfsistat dkimf_addheader(SMFICTX *ctx, char *hname, char *hvalue) { assert(ctx != NULL); assert(hname != NULL); assert(hvalue != NULL); if (testmode) return dkimf_test_addheader(ctx, hname, hvalue); else return smfi_addheader(ctx, hname, hvalue); } /* ** DKIMF_ADDRCPT -- wrapper for smfi_addrcpt() ** ** Parameters: ** ctx -- milter (or test) context ** addr -- address to add ** ** Return value: ** An sfsistat. */ sfsistat dkimf_addrcpt(SMFICTX *ctx, char *addr) { assert(ctx != NULL); assert(addr != NULL); if (testmode) return dkimf_test_addrcpt(ctx, addr); else return smfi_addrcpt(ctx, addr); } /* ** DKIMF_DELRCPT -- wrapper for smfi_delrcpt() ** ** Parameters: ** ctx -- milter (or test) context ** addr -- address to delete ** ** Return value: ** An sfsistat. */ sfsistat dkimf_delrcpt(SMFICTX *ctx, char *addr) { assert(ctx != NULL); assert(addr != NULL); if (testmode) return dkimf_test_delrcpt(ctx, addr); else return smfi_delrcpt(ctx, addr); } /* ** DKIMF_SETREPLY -- wrapper for smfi_setreply() ** ** Parameters: ** ctx -- milter (or test) context ** rcode -- SMTP reply code ** xcode -- SMTP enhanced status code ** replytxt -- reply text ** ** Return value: ** An sfsistat. */ sfsistat dkimf_setreply(SMFICTX *ctx, char *rcode, char *xcode, char *replytxt) { assert(ctx != NULL); if (testmode) return dkimf_test_setreply(ctx, rcode, xcode, replytxt); else return smfi_setreply(ctx, rcode, xcode, replytxt); } /* ** DKIMF_GETSYMVAL -- wrapper for smfi_getsymval() ** ** Parameters: ** ctx -- milter (or test) context ** sym -- symbol to retrieve ** ** Return value: ** Pointer to the value of the requested MTA symbol. */ char * dkimf_getsymval(SMFICTX *ctx, char *sym) { assert(ctx != NULL); assert(sym != NULL); if (testmode) return dkimf_test_getsymval(ctx, sym); else return smfi_getsymval(ctx, sym); } #ifdef USE_LUA /* ** LUA ACCESSOR FUNCTIONS ** ** These are the C sides of the utility functions that will be made available ** to users via Lua to write their own policy scripts. ** ** NAMES: ** Should all start "dkimf_xs_" (for DKIM filter accessors) ** ** PARAMETERS: ** Should all accept nothing more than a single Lua state handle. ** Lua accessor and utility functions are used to pull parameters off ** the stack. ** ** RETURN VALUES: ** Should all return the number of things they want to return via ** the Lua stack. Generally accessors return one thing, and utility ** functions either return a result or a Lua "nil", which means ** at least one thing is always returned. ** ** STACK: ** All functions should first evaluate the stack to see that it's what ** they expect in terms of number and types of elements. The first ** stack item should always be expected to be a "light user data" ** (handle pointer) to a (SMFICTX). If there are no errors, ** collect all the values and pop them. The context pointer may come in ** NULL, in which case the script is being called during configuration ** verification; if so, return an appropriate dummy value from your ** function, if applicable, such as the name of the function or 0 or ** something matching what the script would expect back from ** the function such that the rest of the test will complete. */ /* ** DKIMF_IMPORT_GLOBALS -- add globals to a Lua state ** ** Parameters: ** ctx -- filter context ** l -- Lua state ** ** Return value: ** None. */ void dkimf_import_globals(void *p, lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct msgctx *mctx; struct lua_global *lg; if (p == NULL) return; ctx = (SMFICTX *) p; cc = (struct connctx *) dkimf_getpriv(ctx); mctx = cc->cctx_msg; lg = mctx->mctx_luaglobalh; while (lg != NULL) { switch (lg->lg_type) { case LUA_TNIL: lua_pushnil(l); lua_setglobal(l, lg->lg_name); break; case LUA_TNUMBER: { lua_Number x; memcpy(&x, lg->lg_value, sizeof x); lua_pushnumber(l, x); lua_setglobal(l, lg->lg_name); break; } case LUA_TBOOLEAN: lua_pushboolean(l, (long) lg->lg_value); lua_setglobal(l, lg->lg_name); break; case LUA_TSTRING: lua_pushstring(l, (char *) lg->lg_value); lua_setglobal(l, lg->lg_name); break; default: assert(0); } lg = lg->lg_next; } } /* ** DKIMF_XS_SIGNFOR -- sign as if the mail came from a specified user ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_signfor(lua_State *l) { _Bool multi = FALSE; int top; int status; struct lua_global *lg; SMFICTX *ctx; unsigned char *user = NULL; unsigned char *domain = NULL; struct connctx *cc; struct msgctx *msg; struct dkimf_config *conf; char addr[MAXADDRESS + 1]; char errkey[BUFRSZ + 1]; top = lua_gettop(l); if (top != 2 && top != 3) { lua_pushstring(l, "odkim.signfor(): incorrect argument count"); lua_error(l); } else if (!lua_isuserdata(l, 1) || !lua_isstring(l, 2) || (top == 3 && !lua_isboolean(l, 3))) { lua_pushstring(l, "odkim.signfor(): invalid argument"); lua_error(l); } lua_pop(l, top); ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx == NULL) { lua_pushnil(l); return 1; } strlcpy(addr, lua_tostring(l, 2), sizeof addr); if (top == 3) multi = lua_toboolean(l, 3); cc = (struct connctx *) dkimf_getpriv(ctx); msg = cc->cctx_msg; conf = cc->cctx_config; if (conf->conf_signtabledb == NULL || conf->conf_keytabledb == NULL) { lua_pushnil(l); return 1; } status = dkim_mail_parse(addr, &user, &domain); if (status != 0 || user == NULL || domain == NULL) { lua_pushstring(l, "odkim.signfor(): can't parse address"); lua_error(l); } status = dkimf_apply_signtable(msg, conf->conf_keytabledb, conf->conf_signtabledb, user, domain, errkey, sizeof errkey, multi); if (status == -2 || status == -3) { lua_pushfstring(l, "odkim.signfor(): error processing key '%s'", errkey); lua_error(l); } else if (status == -1) { lua_pushstring(l, "odkim.signfor(): can't read signing table"); lua_error(l); } else { lua_pushnumber(l, status); return 1; } } /* ** DKIMF_XS_EXPORT -- export a global for use in later scripts ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_export(lua_State *l) { int c; int top; int type; struct lua_global *lg; SMFICTX *ctx; struct connctx *cc; struct msgctx *msg; top = lua_gettop(l); if (top < 3 || top % 2 != 1) { lua_pushstring(l, "odkim.export(): incorrect argument count"); lua_error(l); } for (c = 2; c < top; c += 2) { if (!lua_isstring(l, c) || (!lua_isnil(l, c + 1) && !lua_isstring(l, c + 1) && !lua_isnumber(l, c + 1) && !lua_isboolean(l, c + 1))) { lua_pushstring(l, "odkim.export(): incorrect argument type"); lua_error(l); } } ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx == NULL) { lua_pop(l, top); return 0; } cc = (struct connctx *) dkimf_getpriv(ctx); msg = cc->cctx_msg; for (c = 2; c < top; c += 2) { type = lua_type(l, c + 1); if (type != LUA_TNIL && type != LUA_TNUMBER && type != LUA_TBOOLEAN && type != LUA_TSTRING) continue; lg = (struct lua_global *) malloc(sizeof *lg); if (lg != NULL) { lg->lg_name = strdup(lua_tostring(l, c)); if (lg->lg_name == NULL) { free(lg); continue; } lg->lg_type = type; lg->lg_next = NULL; if (msg->mctx_luaglobalh == NULL) msg->mctx_luaglobalh = lg; else msg->mctx_luaglobalt->lg_next = lg; msg->mctx_luaglobalt = lg; switch (lg->lg_type) { case LUA_TNIL: lg->lg_value = NULL; break; case LUA_TNUMBER: lg->lg_value = malloc(sizeof(lua_Number)); if (lg->lg_value != NULL) { lua_Number x; x = lua_tonumber(l, c + 1); memcpy(lg->lg_value, &x, sizeof x); } break; case LUA_TBOOLEAN: if (lua_toboolean(l, c + 1)) lg->lg_value = (void *) 1; else lg->lg_value = (void *) 0; break; case LUA_TSTRING: lg->lg_value = strdup(lua_tostring(l, c + 1)); break; } } } lua_pop(l, top); return 0; } # ifdef _FFR_RBL /* ** DKIMF_XS_RBLCHECK -- do an RBL query ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_rblcheck(lua_State *l) { _Bool found = FALSE; RBL_STAT status; uint32_t res; double timeout = -1.; double i; const char *query; const char *qroot = NULL; void *qh; RBL *rbl; SMFICTX *ctx; struct connctx *cc = NULL; struct dkimf_config *conf; struct timeval to; if (lua_gettop(l) < 3 || lua_gettop(l) > 4) { lua_pushstring(l, "odkim.rbl_check(): incorrect argument count"); lua_error(l); } else if (!lua_isuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isstring(l, 3) || (lua_gettop(l) == 4 && !lua_isnumber(l, 4))) { lua_pushstring(l, "odkim.rbl_check(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx != NULL) cc = (struct connctx *) dkimf_getpriv(ctx); query = lua_tostring(l, 2); qroot = lua_tostring(l, 3); if (lua_gettop(l) == 4) timeout = lua_tonumber(l, 4); lua_pop(l, lua_gettop(l)); if (cc == NULL) return 0; conf = cc->cctx_config; rbl = rbl_init(NULL, NULL, NULL); if (rbl == NULL) { lua_pushstring(l, "odkim.rbl_check(): can't create RBL handle"); lua_error(l); } # ifdef USE_UNBOUND dkimf_rbl_unbound_setup(rbl); # endif /* USE_UNBOUND */ if (conf->conf_nslist != NULL) { status = rbl_dns_nslist(rbl, conf->conf_nslist); if (status != DKIM_STAT_OK) { lua_pushstring(l, "odkim.rbl_check(): can't set nameserver list"); lua_error(l); } } if (conf->conf_trustanchorpath != NULL) { if (access(conf->conf_trustanchorpath, R_OK) != 0) { lua_pushfstring(l, "odkim.rbl_check(): %s: access(): %s", conf->conf_trustanchorpath, strerror(errno)); lua_error(l); } status = rbl_dns_trustanchor(rbl, conf->conf_trustanchorpath); if (status != DKIM_STAT_OK) { lua_pushstring(l, "odkim.rbl_check(): can't set trust anchor"); lua_error(l); } } if (conf->conf_resolverconfig != NULL) { status = rbl_dns_config(rbl, conf->conf_resolverconfig); if (status != DKIM_DNS_SUCCESS) { lua_pushstring(l, "odkim.rbl_check(): can't configure resolver"); lua_error(l); } } rbl_setdomain(rbl, (u_char *) qroot); status = rbl_query_start(rbl, (u_char *) query, &qh); if (status != RBL_STAT_OK) { rbl_close(rbl); lua_pushstring(l, "odkim.rbl_check(): RBL query failed"); lua_error(l); } to.tv_usec = modf(timeout, &i); to.tv_sec = (u_int) i; status = rbl_query_check(rbl, qh, timeout == -1. ? NULL : &to, &res); if (status != RBL_STAT_NOTFOUND && status != RBL_STAT_NOREPLY && status != RBL_STAT_FOUND) lua_pushstring(l, rbl_geterror(rbl)); else if (status == RBL_STAT_FOUND) found = TRUE; rbl_close(rbl); if (status != RBL_STAT_NOTFOUND && status != RBL_STAT_NOREPLY && status != RBL_STAT_FOUND) { return 1; } else if (found) { lua_pushnumber(l, res >> 24); lua_pushnumber(l, (res >> 16) & 0xff); lua_pushnumber(l, (res >> 8) & 0xff); lua_pushnumber(l, res & 0xff); return 4; } else { return 0; } } # endif /* _FFR_RBL */ /* ** DKIMF_XS_XTAG -- add an extension tag ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_xtag(lua_State *l) { SMFICTX *ctx; const char *tag = NULL; const char *value = NULL; if (lua_gettop(l) != 3) { lua_pushstring(l, "odkim.xtag(): incorrect argument count"); lua_error(l); } else if (!lua_isuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isstring(l, 3)) { lua_pushstring(l, "odkim.xtag(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); tag = lua_tostring(l, 2); value = lua_tostring(l, 3); lua_pop(l, 3); if (ctx != NULL) { int n = 0; int status; struct connctx *cc; struct msgctx *dfc; struct signreq *sr; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next) { status = dkim_add_xtag(sr->srq_dkim, tag, value); if (status != DKIM_STAT_OK) { lua_pushnumber(l, -1); return 1; } n++; } lua_pushnumber(l, n); return 1; } else { lua_pushnumber(l, 0); return 1; } } /* ** DKIMF_XS_PARSEFIELD -- parse an address field into its components ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_parsefield(lua_State *l) { unsigned char *user = NULL; unsigned char *domain = NULL; unsigned char field[DKIM_MAXHEADER + 1]; if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.parse_field(): incorrect argument count"); lua_error(l); } else if (!lua_isstring(l, 1)) { lua_pushstring(l, "odkim.parse_field(): incorrect argument type"); lua_error(l); } strlcpy(field, lua_tostring(l, 1), sizeof field); lua_pop(l, 1); if (field == NULL) { lua_pushnil(l); return 1; } else if (dkim_mail_parse(field, &user, &domain) != 0 || user == NULL || domain == NULL) { lua_pushnil(l); return 1; } else { lua_pushstring(l, user); lua_pushstring(l, domain); return 2; } } /* ** DKIMF_XS_LOG -- log a string ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_log(lua_State *l) { SMFICTX *ctx; const char *logstring; if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.log(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "odkim.log(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); logstring = lua_tostring(l, 2); lua_pop(l, 2); if (ctx != NULL) { struct connctx *cc; cc = (struct connctx *) dkimf_getpriv(ctx); if (cc->cctx_config->conf_dolog) syslog(LOG_INFO, "%s", logstring); } lua_pushnil(l); return 1; } /* ** DKIMF_XS_FROMDOMAIN -- retrieve From: domain ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_fromdomain(lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_fromdomain(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_fromdomain(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushstring(l, "dkimf_xs_fromdomain"); } else { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; lua_pushstring(l, (char *) dfc->mctx_domain); } return 1; } /* ** DKIMF_XS_CLIENTHOST -- retrieve client hostname ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_clienthost(lua_State *l) { SMFICTX *ctx; struct connctx *cc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_clienthost(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_clienthost(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushstring(l, "dkimf_xs_clienthost"); } else { cc = (struct connctx *) dkimf_getpriv(ctx); lua_pushstring(l, cc->cctx_host); } return 1; } /* ** DKIMF_XS_CLIENTIP -- retrieve client IP address ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_clientip(lua_State *l) { SMFICTX *ctx; struct connctx *cc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_clientip(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_clientip(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushstring(l, "dkimf_xs_clientip"); } else { char ipbuf[BUFRSZ + 1]; memset(ipbuf, '\0', sizeof ipbuf); cc = (struct connctx *) dkimf_getpriv(ctx); #ifdef AF_INET6 if (cc->cctx_ip.ss_family == AF_INET6) { struct sockaddr_in6 *sa; sa = (struct sockaddr_in6 *) &cc->cctx_ip; if (inet_ntop(AF_INET6, &sa->sin6_addr, ipbuf, sizeof ipbuf) == NULL) { lua_pushnil(l); } else { lua_pushstring(l, ipbuf); } } else #endif /* AF_INET6 */ #ifdef AF_INET if (cc->cctx_ip.ss_family == AF_INET) { struct sockaddr_in *sa; sa = (struct sockaddr_in *) &cc->cctx_ip; if (inet_ntop(AF_INET, &sa->sin_addr, ipbuf, sizeof ipbuf) == NULL) { lua_pushnil(l); } else { lua_pushstring(l, ipbuf); } } else #endif /* AF_INET */ { lua_pushnil(l); } } return 1; } #ifdef _FFR_REPUTATION /* ** DKIMF_XS_SPAM -- tag message as spam ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_spam(lua_State *l) { SMFICTX *ctx; const char *keyname = NULL; const char *ident = NULL; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.spam(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.spam(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx != NULL) { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; dfc->mctx_spam = TRUE; } lua_pop(l, 1); return 0; } #endif /* _FFR_REPUTATION */ /* ** DKIMF_XS_REQUESTSIG -- request a signature ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_requestsig(lua_State *l) { int top; ssize_t signlen = (ssize_t) -1; SMFICTX *ctx; const char *keyname = NULL; const char *ident = NULL; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; assert(l != NULL); top = lua_gettop(l); if (top == 0 && top > 4) { lua_pushstring(l, "odkim.sign(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || (top > 1 && !lua_isstring(l, 2)) || (top > 2 && !lua_isstring(l, 3) && !lua_isnumber(l, 3)) || (top > 3 && !lua_isstring(l, 4) && !lua_isnumber(l, 4))) { lua_pushstring(l, "odkim.sign(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx != NULL) { int c; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; conf = cc->cctx_config; for (c = 2; c <= top; c++) { if (c == 2) { keyname = lua_tostring(l, 2); } else if (lua_type(l, c) == LUA_TNUMBER) { if (signlen != (ssize_t) -1) { lua_pushstring(l, "odkim.sign(): incorrect argument type"); lua_error(l); } signlen = (ssize_t) lua_tonumber(l, c); } else { if (ident != NULL) { lua_pushstring(l, "odkim.sign(): incorrect argument type"); lua_error(l); } ident = lua_tostring(l, c); } } } lua_pop(l, top); if (ident != NULL && ident[0] == '\0') ident = NULL; if (ctx == NULL) { lua_pushnumber(l, 0); return 1; } if (conf->conf_keytabledb == NULL && keyname != NULL) { lua_pushstring(l, "odkim.sign(): request requires KeyTable"); lua_error(l); } /* try to get the key */ if (keyname != NULL) { switch (dkimf_add_signrequest(dfc, conf->conf_keytabledb, (char *) keyname, (char *) ident, signlen)) { case 3: if (conf->conf_dolog) { syslog(LOG_ERR, "key '%s' could not be applied", keyname); } lua_pushnumber(l, 0); return 1; case 2: if (conf->conf_dolog) { syslog(LOG_ERR, "key '%s' could not be loaded", keyname); } lua_pushnumber(l, 0); return 1; case 1: if (conf->conf_dolog) syslog(LOG_ERR, "key '%s' not found", keyname); lua_pushnumber(l, 0); return 1; case -1: if (conf->conf_dolog) { syslog(LOG_ERR, "error requesting key '%s'", keyname); } lua_pushnumber(l, 0); return 1; } } else if (dkimf_add_signrequest(dfc, NULL, NULL, (char *) ident, (ssize_t) -1) != 0) { if (conf->conf_dolog) syslog(LOG_ERR, "failed to load/apply default key"); lua_pushnumber(l, 0); return 1; } dfc->mctx_signalg = conf->conf_signalg; lua_pushnumber(l, 1); return 1; } /* ** DKIMF_XS_REPLACEHEADER -- replace a header field's value ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_replaceheader(lua_State *l) { int idx; const char *hdrname; const char *newval; SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; Header hdr; assert(l != NULL); if (lua_gettop(l) != 4) { lua_pushstring(l, "odkim.replace_header(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isnumber(l, 3) || !lua_isstring(l, 4)) { lua_pushstring(l, "odkim.replace_header(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); hdrname = lua_tostring(l, 2); idx = (int) lua_tonumber(l, 3); newval = lua_tostring(l, 4); if (ctx != NULL) { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; conf = cc->cctx_config; } lua_pop(l, 3); if (ctx == NULL) { if (idx == 0) lua_pushstring(l, "dkimf_xs_replaceheader"); else lua_pushnil(l); return 1; } hdr = dkimf_findheader(dfc, (char *) hdrname, idx); if (hdr == NULL) { lua_pushnil(l); return 1; } else { char *tmp; if (ctx != NULL && cc->cctx_noleadspc) { size_t len; len = strlen(newval); tmp = malloc(len + 2); if (tmp == NULL) { lua_pushnil(l); return 1; } tmp[0] = ' '; memcpy(&tmp[1], newval, len + 1); } else { tmp = strdup(newval); if (tmp == NULL) { lua_pushnil(l); return 1; } } free(hdr->hdr_val); hdr->hdr_val = tmp; return 0; } } /* ** DKIMF_XS_GETENVFROM -- request envelope sender ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getenvfrom(lua_State *l) { int idx; const char *hdrname; SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; Header hdr; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_envfrom(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_envfrom(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx != NULL) { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; } lua_pop(l, 1); if (ctx == NULL) lua_pushstring(l, "dkimf_xs_getenvfrom"); else lua_pushstring(l, dfc->mctx_envfrom); return 1; } /* ** DKIMF_XS_GETHEADER -- request a header value ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getheader(lua_State *l) { int idx; const char *hdrname; SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; Header hdr; assert(l != NULL); if (lua_gettop(l) != 3) { lua_pushstring(l, "odkim.get_header(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isnumber(l, 3)) { lua_pushstring(l, "odkim.get_header(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); hdrname = lua_tostring(l, 2); idx = (int) lua_tonumber(l, 3); if (ctx != NULL) { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; conf = cc->cctx_config; } lua_pop(l, 3); if (ctx == NULL) { if (idx == 0) lua_pushstring(l, "dkimf_xs_getheader"); else lua_pushnil(l); return 1; } hdr = dkimf_findheader(dfc, (char *) hdrname, idx); if (hdr == NULL) { lua_pushnil(l); return 1; } else { lua_pushstring(l, hdr->hdr_val); return 1; } } /* ** DKIMF_XS_POPAUTH -- see if the client's IP address is in the POPAUTH ** database ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_popauth(lua_State *l) { SMFICTX *ctx; struct connctx *cc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.check_popauth(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.check_popauth(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushnumber(l, 0); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); #ifdef POPAUTH if (popdb == NULL) { lua_pushnil(l); return 1; } else { _Bool popauth; popauth = dkimf_checkpopauth(popdb, &cc->cctx_ip); lua_pushnumber(l, popauth ? 1 : 0); return 1; } #else /* POPAUTH */ lua_pushnil(l); return 1; #endif /* POPAUTH */ } /* ** DKIMF_XS_INTERNALIP -- see if the client's IP address is "internal" ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_internalip(lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct dkimf_config *conf; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.internal_ip(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.internal_ip(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushnumber(l, 1); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); conf = cc->cctx_config; if (conf->conf_internal == NULL) { lua_pushnumber(l, 0); } else { _Bool internal; internal = dkimf_checkhost(conf->conf_internal, cc->cctx_host); internal = internal || dkimf_checkip(conf->conf_internal, (struct sockaddr *) &cc->cctx_ip); lua_pushnumber(l, internal ? 1 : 0); } return 1; } /* ** DKIMF_XS_DBOPEN -- open a DB handle ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_dbopen(lua_State *l) { unsigned int flags = DKIMF_DB_FLAG_READONLY; int status; DKIMF_DB db; char *name; char *err = NULL; struct dkimf_lua_gc *gc; assert(l != NULL); if (lua_gettop(l) != 1 && lua_gettop(l) != 2) { lua_pushstring(l, "odkim.db_open(): incorrect argument count"); lua_error(l); } else if (!lua_isstring(l, 1) || (lua_gettop(l) == 2 && !lua_isboolean(l, 2))) { lua_pushstring(l, "odkim.db_open(): incorrect argument type"); lua_error(l); } name = (char *)lua_tostring(l, 1); if (lua_gettop(l) == 2 && lua_toboolean(l, 2)) flags |= DKIMF_DB_FLAG_ICASE; lua_pop(l, lua_gettop(l)); status = dkimf_db_open(&db, name, flags, NULL, &err); if (status != 0) { if (err != NULL) { lua_pushfstring(l, "%s: odkim.db_open(): %s", name, err); } else { lua_pushfstring(l, "%s: odkim.db_open() failed", name); } lua_error(l); } lua_getglobal(l, DKIMF_GC); gc = (struct dkimf_lua_gc *) lua_touserdata(l, 1); lua_pop(l, 1); dkimf_lua_gc_add(gc, db, DKIMF_LUA_GC_DB); lua_pushlightuserdata(l, db); return 1; } /* ** DKIMF_XS_DBCLOSE -- close a DB handle ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_dbclose(lua_State *l) { DKIMF_DB db; struct dkimf_lua_gc *gc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.db_close(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.db_close(): incorrect argument type"); lua_error(l); } db = (DKIMF_DB) lua_touserdata(l, 1); lua_pop(l, 1); if (db == NULL) { lua_pushnumber(l, 0); return 1; } (void) dkimf_db_close(db); lua_getglobal(l, DKIMF_GC); gc = (struct dkimf_lua_gc *) lua_touserdata(l, 1); lua_pop(l, 1); dkimf_lua_gc_remove(gc, (void *) db); lua_pushnumber(l, 1); return 1; } /* ** DKIMF_XS_DBHANDLE -- retrieve a DB handle ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_dbhandle(lua_State *l) { int code; SMFICTX *ctx; struct connctx *cc; struct dkimf_config *conf; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.get_dbhandle(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "odkim.get_dbhandle(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); if (ctx == NULL) { lua_pop(l, 2); lua_pushnil(l); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); conf = cc->cctx_config; code = (int) lua_tonumber(l, 1); lua_pop(l, 2); switch (code) { case DB_DOMAINS: if (conf->conf_domainsdb == NULL) lua_pushnil(l); else lua_pushlightuserdata(l, conf->conf_domainsdb); break; case DB_THIRDPARTY: if (conf->conf_thirdpartydb == NULL) lua_pushnil(l); else lua_pushlightuserdata(l, conf->conf_thirdpartydb); break; case DB_DONTSIGNTO: if (conf->conf_dontsigntodb == NULL) lua_pushnil(l); else lua_pushlightuserdata(l, conf->conf_dontsigntodb); break; case DB_MTAS: if (conf->conf_mtasdb == NULL) lua_pushnil(l); else lua_pushlightuserdata(l, conf->conf_mtasdb); break; case DB_MACROS: if (conf->conf_macrosdb == NULL) lua_pushnil(l); else lua_pushlightuserdata(l, conf->conf_macrosdb); break; case DB_SIGNINGTABLE: if (conf->conf_signtabledb == NULL) lua_pushnil(l); else lua_pushlightuserdata(l, conf->conf_signtabledb); break; default: lua_pushnil(l); break; } return 1; } /* ** DKIMF_XS_RCPTCOUNT -- retrieve recipient count ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_rcptcount(lua_State *l) { int rcnt; SMFICTX *ctx; struct connctx *cc; struct dkimf_config *conf; struct msgctx *dfc; struct addrlist *addr; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.rcpt_count(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.rcpt_count(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushnumber(l, 1); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); conf = cc->cctx_config; dfc = cc->cctx_msg; rcnt = 0; for (addr = dfc->mctx_rcptlist; addr != NULL; addr = addr->a_next) rcnt++; lua_pushnumber(l, rcnt); return 1; } /* ** DKIMF_XS_RCPT -- retrieve an envelope recipient ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_rcpt(lua_State *l) { int rcnt; SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; struct addrlist *addr; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.get_rcpt(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "odkim.get_rcpt(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); rcnt = (int) lua_tonumber(l, 1); lua_pop(l, 2); if (ctx == NULL) { lua_pushstring(l, "dkimf_xs_rcpt"); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; addr = dfc->mctx_rcptlist; while (rcnt > 0 && addr != NULL) { addr = addr->a_next; rcnt--; } if (addr == NULL) lua_pushnil(l); else lua_pushstring(l, addr->a_addr); return 1; } /* ** DKIMF_XS_RCPTARRAY -- retrieve all recipients into a Lua array ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_rcptarray(lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_rcptarray(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_rcptarray(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); lua_newtable(l); if (ctx == NULL) { lua_pushnumber(l, 1); lua_pushstring(l, "dkimf_xs_rcptarray"); lua_settable(l, -3); } else { int idx; struct addrlist *addr; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; for (addr = dfc->mctx_rcptlist, idx = 1; addr != NULL; addr = addr->a_next, idx++) { lua_pushnumber(l, idx); lua_pushstring(l, addr->a_addr); lua_settable(l, -3); } } return 1; } /* ** DKIMF_XS_DBQUERY -- check for a record in a database ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_dbquery(lua_State *l) { int status; _Bool exists; DKIMF_DB db; const char *str; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.db_check(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "odkim.db_check(): incorrect argument type"); lua_error(l); } db = (DKIMF_DB) lua_touserdata(l, 1); str = lua_tostring(l, 2); lua_pop(l, 2); if (db == NULL || str == NULL) { lua_pushnil(l); return 1; } exists = FALSE; status = dkimf_db_get(db, (char *) str, 0, NULL, 0, &exists); if (status == 0) lua_pushnumber(l, exists ? 1 : 0); else lua_pushnil(l); return 1; } /* ** DKIMF_XS_SETPARTIAL -- request l= tags ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_setpartial(lua_State *l) { SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.use_ltag(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.use_ltag(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx != NULL) { struct connctx *cc; struct msgctx *dfc; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; dfc->mctx_ltag = TRUE; } lua_pushnil(l); return 1; } /* ** DKIMF_XS_VERIFY -- set up verification ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_verify(lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.verify(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.verify(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx != NULL) { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; conf = cc->cctx_config; if (dfc->mctx_dkimv == NULL) { DKIM_STAT status; dfc->mctx_dkimv = dkim_verify(conf->conf_libopendkim, dfc->mctx_jobid, NULL, &status); if (dfc->mctx_dkimv == NULL) { lua_pushstring(l, dkim_getresultstr(status)); return 1; } } } lua_pushnil(l); return 1; } /* ** DKIMF_XS_GETSIGARRAY -- get signature handle array ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getsigarray(lua_State *l) { SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_sigarray(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_sigarray(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx != NULL) { struct connctx *cc; struct msgctx *dfc; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; if (dfc->mctx_dkimv == NULL) { lua_pushnumber(l, 0); } else { int nsigs; DKIM_STAT status; DKIM_SIGINFO **sigs; status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status != DKIM_STAT_OK) { lua_pushnil(l); } else { int c; lua_newtable(l); for (c = 0; c < nsigs; c++) { lua_pushnumber(l, c + 1); lua_pushlightuserdata(l, sigs[c]); lua_settable(l, -3); } } } } else { lua_pushnil(l); } return 1; } /* ** DKIMF_XS_GETSIGCOUNT -- get signature count ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getsigcount(lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.get_sigcount(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.get_sigcount(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx != NULL) { cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; if (dfc->mctx_dkimv == NULL) { lua_pushnumber(l, 0); } else { DKIM_STAT status; int nsigs; DKIM_SIGINFO **sigs; status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status != DKIM_STAT_OK) lua_pushnil(l); else lua_pushnumber(l, nsigs); } } else { lua_pushnumber(l, 1); } return 1; } /* ** DKIMF_XS_GETSIGHANDLE -- get signature handle ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getsighandle(lua_State *l) { int idx; int nsigs; DKIM_STAT status; SMFICTX *ctx; DKIM_SIGINFO **sigs; struct connctx *cc; struct msgctx *dfc; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.get_sighandle(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "odkim.get_sighandle(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); idx = (int) lua_tonumber(l, 2); lua_pop(l, 2); if (ctx == NULL) { lua_pushlightuserdata(l, NULL); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; if (dfc->mctx_dkimv == NULL) { lua_pushnil(l); return 1; } status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status != DKIM_STAT_OK) { lua_pushnil(l); return 1; } if (idx < 0 || idx >= nsigs) { lua_pushstring(l, "odkim.get_sighandle(): invalid request"); lua_error(l); } lua_pushlightuserdata(l, sigs[idx]); return 1; } /* ** DKIMF_XS_GETSIGDOMAIN -- get signature's signing domain ("d=") ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getsigdomain(lua_State *l) { DKIM_SIGINFO *sig; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.sig_getdomain(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.sig_getdomain(): incorrect argument type"); lua_error(l); } sig = (DKIM_SIGINFO *) lua_touserdata(l, 1); lua_pop(l, 1); if (sig == NULL) lua_pushlightuserdata(l, NULL); else lua_pushstring(l, (char *) dkim_sig_getdomain(sig)); return 1; } /* ** DKIMF_XS_SIGIGNORE -- ignore a signature and its result ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_sigignore(lua_State *l) { DKIM_SIGINFO *sig; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.sig_getdomain(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.sig_getdomain(): incorrect argument type"); lua_error(l); } sig = (DKIM_SIGINFO *) lua_touserdata(l, 1); lua_pop(l, 1); if (sig != NULL) dkim_sig_ignore(sig); lua_pushnil(l); return 1; } /* ** DKIMF_XS_GETSIGIDENTITY -- get signature's signing identity ("i=") ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getsigidentity(lua_State *l) { DKIM_STAT status; DKIM_SIGINFO *sig; u_char addr[MAXADDRESS + 1]; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.sig_getidentity(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.sig_getidentity(): incorrect argument type"); lua_error(l); } sig = (DKIM_SIGINFO *) lua_touserdata(l, 1); lua_pop(l, 1); if (sig == NULL) { lua_pushstring(l, "dkimf_xs_getsigidentity"); return 1; } memset(addr, '\0', sizeof addr); status = dkim_sig_getidentity(NULL, sig, addr, sizeof addr - 1); if (status != DKIM_STAT_OK) lua_pushnil(l); else lua_pushstring(l, (char *) addr); return 1; } /* ** DKIMF_XS_GETSYMVAL -- get MTA symbol ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_getsymval(lua_State *l) { char *name; char *sym; SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.get_mtasymbol(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "odkim.get_mtasymbol(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); name = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (ctx == NULL) { lua_pushstring(l, "dkimf_xs_getmtasymbol"); } else { sym = dkimf_getsymval(ctx, name); if (sym == NULL) lua_pushnil(l); else lua_pushstring(l, sym); } return 1; } /* ** DKIMF_XS_SIGRESULT -- get signature's result code ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_sigresult(lua_State *l) { DKIM_SIGINFO *sig; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.sig_result(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.sig_result(): incorrect argument type"); lua_error(l); } sig = (DKIM_SIGINFO *) lua_touserdata(l, 1); lua_pop(l, 1); if (sig == NULL) lua_pushnumber(l, 0); else lua_pushnumber(l, dkim_sig_geterror(sig)); return 1; } /* ** DKIMF_XS_SIGBHRESULT -- get signature's body hash result code ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_sigbhresult(lua_State *l) { DKIM_SIGINFO *sig; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.sig_bhresult(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.sig_bhresult(): incorrect argument type"); lua_error(l); } sig = (DKIM_SIGINFO *) lua_touserdata(l, 1); lua_pop(l, 1); if (sig == NULL) lua_pushnumber(l, 0); else lua_pushnumber(l, dkim_sig_getbh(sig)); return 1; } /* ** DKIMF_XS_BODYLENGTH -- return total body length ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_bodylength(lua_State *l) { ssize_t body; DKIM_STAT status; SMFICTX *ctx; DKIM_SIGINFO *sig; struct connctx *cc; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.sig_bodylength(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_islightuserdata(l, 2)) { lua_pushstring(l, "odkim.sig_bodylength(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); sig = (DKIM_SIGINFO *) lua_touserdata(l, 2); lua_pop(l, 2); if (ctx == NULL) { lua_pushnumber(l, 100); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); if (cc->cctx_msg == NULL || cc->cctx_msg->mctx_dkimv == NULL) { lua_pushnil(l); return 1; } status = dkim_sig_getcanonlen(cc->cctx_msg->mctx_dkimv, sig, &body, NULL, NULL); if (status != DKIM_STAT_OK) lua_pushnil(l); else lua_pushnumber(l, body); return 1; } /* ** DKIMF_XS_CANONLENGTH -- return length canonicalized by a signature ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_canonlength(lua_State *l) { ssize_t cl; DKIM_STAT status; SMFICTX *ctx; DKIM_SIGINFO *sig; struct connctx *cc; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.sig_canonlength(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_islightuserdata(l, 2)) { lua_pushstring(l, "odkim.sig_canonlength(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); sig = (DKIM_SIGINFO *) lua_touserdata(l, 2); lua_pop(l, 2); if (ctx == NULL) { lua_pushnumber(l, 100); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); if (cc->cctx_msg == NULL || cc->cctx_msg->mctx_dkimv == NULL) { lua_pushnil(l); return 1; } status = dkim_sig_getcanonlen(cc->cctx_msg->mctx_dkimv, sig, NULL, &cl, NULL); if (status != DKIM_STAT_OK) lua_pushnil(l); else lua_pushnumber(l, cl); return 1; } /* ** DKIMF_XS_ADDHEADER -- add a header field ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_addheader(lua_State *l) { char *name; char *value; SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 3) { lua_pushstring(l, "odkim.add_header(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isstring(l, 3)) { lua_pushstring(l, "odkim.add_header(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); name = (char *) lua_tostring(l, 2); value = (char *) lua_tostring(l, 3); lua_pop(l, 3); if (ctx == NULL) lua_pushnil(l); else if (dkimf_insheader(ctx, 1, name, value) == MI_SUCCESS) lua_pushnumber(l, 1); else lua_pushnil(l); return 1; } /* ** DKIMF_XS_DELHEADER -- delete a header field ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_delheader(lua_State *l) { int idx; char *name; SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 3) { lua_pushstring(l, "odkim.del_header(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isnumber(l, 3)) { lua_pushstring(l, "odkim.del_header(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); name = (char *) lua_tostring(l, 2); idx = lua_tonumber(l, 3); lua_pop(l, 3); if (ctx == NULL) lua_pushnil(l); else if (dkimf_chgheader(ctx, name, 1, NULL) == MI_SUCCESS) lua_pushnumber(l, 1); else lua_pushnil(l); return 1; } /* ** DKIMF_XS_ADDRCPT -- add a recipient ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_addrcpt(lua_State *l) { char *addr; SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.add_rcpt(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "odkim.add_rcpt(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); addr = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (ctx == NULL) lua_pushnumber(l, 1); else if (dkimf_addrcpt(ctx, addr) == MI_SUCCESS) lua_pushnumber(l, 1); else lua_pushnil(l); return 1; } /* ** DKIMF_XS_DELRCPT -- delete a recipient ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_delrcpt(lua_State *l) { char *addr; struct addrlist *a; SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; struct dkimf_config *conf; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.delete_rcpt(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "odkim.delete_rcpt(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); addr = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (ctx == NULL) { lua_pushnumber(l, 1); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); conf = cc->cctx_config; dfc = cc->cctx_msg; /* see if this is a known recipient */ for (a = dfc->mctx_rcptlist; a != NULL; a = a->a_next) { if (strcasecmp(a->a_addr, addr) == 0) break; } /* if not found, report error */ if (a == NULL) { lua_pushnil(l); return 1; } /* delete and replace with a header field */ if (dkimf_delrcpt(ctx, a->a_addr) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: smfi_delrcpt() failed", dfc->mctx_jobid); } } else { char header[MAXADDRESS + 8]; snprintf(header, sizeof header, "rfc822;%s", a->a_addr); if (dkimf_addheader(ctx, ORCPTHEADER, header) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: smfi_addheader() failed", dfc->mctx_jobid); } } } lua_pushnumber(l, 1); return 1; } /* ** DKIMF_XS_RESIGN -- set up for re-signing ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_resign(lua_State *l) { SMFICTX *ctx; struct connctx *cc; struct msgctx *dfc; assert(l != NULL); if (lua_gettop(l) != 1) { lua_pushstring(l, "odkim.resign(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1)) { lua_pushstring(l, "odkim.resign(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); lua_pop(l, 1); if (ctx == NULL) { lua_pushnumber(l, 1); return 1; } cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; # ifdef _FFR_RESIGN dfc->mctx_resign = TRUE; lua_pushnumber(l, 1); # else /* _FFR_RESIGN */ lua_pushnil(l); # endif /* _FFR_RESIGN */ return 1; } /* ** DKIMF_XS_SETREPLY -- set SMTP reply text ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_setreply(lua_State *l) { SMFICTX *ctx; char *rcode = NULL; char *xcode = NULL; char *message = NULL; assert(l != NULL); if (lua_gettop(l) != 4) { lua_pushstring(l, "odkim.set_reply(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isstring(l, 3) || !lua_isstring(l, 4)) { lua_pushstring(l, "odkim.set_reply(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); rcode = (char *) lua_tostring(l, 2); xcode = (char *) lua_tostring(l, 3); message = (char *) lua_tostring(l, 4); lua_pop(l, 4); if (ctx == NULL) { lua_pushnumber(l, 1); return 1; } if (strlen(xcode) == 0) xcode = NULL; if (dkimf_setreply(ctx, rcode, xcode, message) == MI_FAILURE) lua_pushnil(l); else lua_pushnumber(l, 1); return 1; } /* ** DKIMF_XS_QUARANTINE -- request quarantine ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_quarantine(lua_State *l) { SMFICTX *ctx; char *message = NULL; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.quarantine(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2)) { lua_pushstring(l, "odkim.quarantine(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); message = (char *) lua_tostring(l, 2); lua_pop(l, 2); if (ctx == NULL) lua_pushnumber(l, 1); else if (dkimf_quarantine(ctx, message) == MI_FAILURE) lua_pushnil(l); else lua_pushnumber(l, 1); return 1; } /* ** DKIMF_XS_SETRESULT -- set milter result ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_setresult(lua_State *l) { SMFICTX *ctx; int mresult; assert(l != NULL); if (lua_gettop(l) != 2) { lua_pushstring(l, "odkim.set_result(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isnumber(l, 2)) { lua_pushstring(l, "odkim.set_result(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); mresult = (int) lua_tonumber(l, 2); lua_pop(l, 2); if (ctx == NULL) { lua_pushnumber(l, 1); } else if (mresult == SMFIS_TEMPFAIL || mresult == SMFIS_ACCEPT || mresult == SMFIS_DISCARD || mresult == SMFIS_REJECT) { struct msgctx *dfc; struct connctx *cc; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; dfc->mctx_mresult = mresult; lua_pushnumber(l, 1); } else { lua_pushnil(l); } return 1; } # ifdef _FFR_STATSEXT /* ** DKIMF_XS_STATSEXT -- record extended statistics ** ** Parameters: ** l -- Lua state ** ** Return value: ** Number of stack items pushed. */ int dkimf_xs_statsext(lua_State *l) { char *name; char *value; SMFICTX *ctx; assert(l != NULL); if (lua_gettop(l) != 3) { lua_pushstring(l, "odkim.stats(): incorrect argument count"); lua_error(l); } else if (!lua_islightuserdata(l, 1) || !lua_isstring(l, 2) || !lua_isstring(l, 3)) { lua_pushstring(l, "odkim.stats(): incorrect argument type"); lua_error(l); } ctx = (SMFICTX *) lua_touserdata(l, 1); name = (char *) lua_tostring(l, 2); value = (char *) lua_tostring(l, 3); lua_pop(l, 3); if (ctx != NULL) { struct statsext *se; struct connctx *cc; struct msgctx *dfc; cc = (struct connctx *) dkimf_getpriv(ctx); dfc = cc->cctx_msg; se = (struct statsext *) malloc(sizeof(struct statsext)); if (se == NULL) { lua_pushfstring(l, "odkim.stats(): malloc(): %s", strerror(errno)); lua_error(l); } se->se_next = dfc->mctx_statsext; dfc->mctx_statsext = se; strlcpy(se->se_name, name, sizeof se->se_name); strlcpy(se->se_value, value, sizeof se->se_value); } lua_pushnil(l); return 1; } # endif /* _FFR_STATSEXT */ #endif /* USE_LUA */ #ifdef _FFR_VBR /* ** DKIMF_VALID_VBR -- determine whether or not VBR should be verified ** ** Parameters: ** dfc -- filter context ** ** Return value: ** TRUE iff the message should have its VBR data checked */ static _Bool dkimf_valid_vbr(struct msgctx *dfc) { _Bool ret; int c = 0; char *p; char *q; char *last = NULL; Header hdr; char mc[DKIM_MAXHEADER + 1]; char tmp[DKIM_MAXHEADER + 1]; assert(dfc != NULL); memset(mc, '\0', sizeof mc); for (c = 0; c == 0 || ret; c++) { hdr = dkimf_findheader(dfc, VBR_INFOHEADER, c); if (hdr == NULL) break; if (c == 0) ret = TRUE; strlcpy(tmp, hdr->hdr_val, sizeof tmp); for (p = strtok_r(tmp, ";", &last); p != NULL; p = strtok_r(NULL, ";", &last)) { q = strchr(p, '='); if (q == NULL) continue; *q = '\0'; dkimf_trimspaces(p); dkimf_trimspaces(q + 1); if (strcasecmp(p, "mc") == 0) { if (mc[0] == '\0') strlcpy(mc, q + 1, sizeof mc); else if (strcasecmp(q + 1, mc) != 0) ret = FALSE; break; } } } if (mc[0] == '\0') ret = FALSE; return ret; } #endif /* _FFR_VBR */ /* ** DKIMF_ADD_AR_FIELDS -- add Authentication-Results header fields ** ** Parameters: ** dfc -- filter context ** conf -- configuration handle ** ctx -- milter context ** ** Return value: ** None. */ static void dkimf_add_ar_fields(struct msgctx *dfc, struct dkimf_config *conf, SMFICTX *ctx) { assert(dfc != NULL); assert(conf != NULL); assert(ctx != NULL); if (dkimf_insheader(ctx, 1, AUTHRESULTSHDR, (char *) dfc->mctx_dkimar) == MI_FAILURE) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header add failed", dfc->mctx_jobid, AUTHRESULTSHDR); } } } /* ** DKIMF_DB_ERROR -- syslog errors related to db retrieval ** ** Parameters: ** db -- the db ** key -- what was looked up ** ** Return value: ** None. */ static void dkimf_db_error(DKIMF_DB db, const char *key) { char errbuf[BUFRSZ]; assert(db != NULL); assert(key != NULL); (void) dkimf_db_strerror(db, errbuf, sizeof errbuf); syslog(LOG_ERR, "error looking up \"%s\" in database: %s", key, errbuf); } /* ** DKIMF_INIT_SYSLOG -- initialize syslog() ** ** Parameters: ** facility -- name of the syslog facility to use when logging; ** can be NULL to request the default ** ** Return value: ** None. */ static void dkimf_init_syslog(char *name, char *facility) { #ifdef LOG_MAIL int code; struct lookup *p = NULL; closelog(); code = LOG_MAIL; if (facility != NULL) { for (p = log_facilities; p != NULL; p++) { if (strcasecmp(p->str, facility) == 0) { code = p->code; break; } } } openlog(name != NULL ? name : progname, LOG_PID, code); #else /* LOG_MAIL */ closelog(); openlog(name != NULL ? name : progname, LOG_PID); #endif /* LOG_MAIL */ } /* ** DKIMF_RESTART_CHECK -- initialize/check restart rate information ** ** Parameters: ** n -- size of restart rate array to initialize/enforce ** t -- maximum time range for restarts (0 == init) ** ** Return value: ** TRUE -- OK to continue ** FALSE -- error */ static _Bool dkimf_restart_check(int n, time_t t) { static int idx; /* last filled slot */ static int alen; /* allocated length */ static time_t *list; if (t == 0) { alen = n * sizeof(time_t); list = (time_t *) malloc(alen); if (list == NULL) return FALSE; memset(list, '\0', alen); idx = 0; alen = n; return TRUE; } else { int which; time_t now; (void) time(&now); which = (idx - 1) % alen; if (which == -1) which = alen - 1; if (list[which] != 0 && list[which] + t > now) return FALSE; list[which] = now; idx++; return TRUE; } } /* ** DKIMF_REPTOKEN -- replace a token in an input string with another string ** ** Parameters: ** out -- output buffer ** outlen -- output buffer length ** in -- input string ** sub -- substitution string ** ** Return value: ** Bytes of output; may be larger than "outlen" if "out" was too small. */ size_t dkimf_reptoken(u_char *out, size_t outlen, u_char *in, u_char *sub) { size_t ret = 0; u_char *p; u_char *q; u_char *end; assert(out != NULL); assert(in != NULL); assert(sub != NULL); memset(out, '\0', outlen); q = out; end = q + outlen - 1; for (p = in; *p != '\0'; p++) { if (*p == '%') { size_t c; c = strlcpy((char *) q, (char *) sub, outlen - ret); q += c; ret += c; } else { if (q < end) { *q = *p; q++; ret++; } } } return ret; } /* ** DKIMF_CHECKFSNODE -- check a filesystem node for safety ** ** Parameters: ** path -- path of the node to check ** myuid -- executing user's effective uid ** myname -- executing user's login ** ino -- evaluated inode (returned) ** err -- error buffer ** errlen -- error buffer length ** ** Return value: ** 1 -- node is safe to use ** 0 -- node is not safe to use ** -1 -- error (check errno) ** ** Notes: ** "Safe" here means the target file cannot be read or written by anyone ** other than the executing user and the superuser. The entire directory ** tree is checked from the root down after resolution of symlinks and ** references to "." and ".." looking for errant "write" bits on ** directories and the file itself. ** ** To prevent attacks through symbolic links, this function also returns ** the inode of the object it evaluated if that object was a file. Thus, ** if the caller first opens the file but doesn't read from it, then the ** returned inode can be compared to the inode of the opened descriptor ** to ensure that what was opened was safe at the time open() was called. ** An inode of -1 is reported if some directory above the target was ** sufficiently locked down that the inode comparison isn't necessary. ** ** This still isn't bulletproof; there's a race between the time of the ** open() call and the result returned by this function. I'm not sure if ** that can be improved. */ static int dkimf_checkfsnode(const char *path, uid_t myuid, char *myname, ino_t *ino, char *err, size_t errlen) { int status; struct passwd *pw; struct group *gr; struct stat s; assert(path != NULL); assert(myname != NULL); assert(ino != NULL); status = stat(path, &s); if (status != 0) return -1; if (S_ISREG(s.st_mode)) { /* owned by root or by me */ if (s.st_uid != 0 && s.st_uid != myuid) { if (err != NULL) { snprintf(err, errlen, "%s is not owned by the executing uid (%d)%s", path, myuid, myuid != 0 ? " or the superuser" : ""); } return 0; } /* if group read/write, the group is only me and/or root */ if ((s.st_mode & (S_IRGRP|S_IWGRP)) != 0) { int c; /* check if anyone else has this file's gid */ pthread_mutex_lock(&pwdb_lock); setpwent(); for (pw = getpwent(); pw != NULL; pw = getpwent()) { if (pw->pw_uid != myuid && pw->pw_uid != 0 && s.st_gid == pw->pw_gid) { if (err != NULL) { snprintf(err, errlen, "%s is in group %u which has multiple users (e.g. \"%s\")", path, s.st_gid, pw->pw_name); } pthread_mutex_unlock(&pwdb_lock); return 0; } } endpwent(); /* check if this group contains anyone else */ gr = getgrgid(s.st_gid); if (gr == NULL) { pthread_mutex_unlock(&pwdb_lock); return -1; } for (c = 0; gr->gr_mem[c] != NULL; c++) { if (strcmp(gr->gr_mem[c], myname) != 0 && strcmp(gr->gr_mem[c], SUPERUSER) != 0) { if (err != NULL) { snprintf(err, errlen, "%s is in group %u which has multiple users (e.g., \"%s\")", path, s.st_gid, gr->gr_mem[c]); } pthread_mutex_unlock(&pwdb_lock); return 0; } } pthread_mutex_unlock(&pwdb_lock); } /* not read/write by others */ if ((s.st_mode & (S_IROTH|S_IWOTH)) != 0) { if (err != NULL) { snprintf(err, errlen, "%s can be read or written by other users", path); } return 0; } *ino = s.st_ino; } else if (S_ISDIR(s.st_mode)) { /* other write needs to be off */ if ((s.st_mode & S_IWOTH) != 0) { if (err != NULL) { snprintf(err, errlen, "%s can be read or written by other users", path); } return 0; } /* group write needs to be super-user or me only */ if ((s.st_mode & S_IWGRP) != 0) { int c; /* check if anyone else has this file's gid */ pthread_mutex_lock(&pwdb_lock); setpwent(); for (pw = getpwent(); pw != NULL; pw = getpwent()) { if (pw->pw_uid != myuid && pw->pw_uid != 0 && s.st_gid == pw->pw_gid) { if (err != NULL) { snprintf(err, errlen, "%s is in group %u which has multiple users (e.g., \"%s\")", myname, s.st_gid, pw->pw_name); } pthread_mutex_unlock(&pwdb_lock); return 0; } } /* check if this group contains anyone else */ gr = getgrgid(s.st_gid); if (gr == NULL) { pthread_mutex_unlock(&pwdb_lock); return -1; } for (c = 0; gr->gr_mem[c] != NULL; c++) { if (strcmp(gr->gr_mem[c], myname) != 0 && strcmp(gr->gr_mem[c], SUPERUSER) != 0) { if (err != NULL) { snprintf(err, errlen, "%s is in group %u which has multiple users (e.g., \"%s\")", myname, s.st_gid, gr->gr_mem[c]); } pthread_mutex_unlock(&pwdb_lock); return 0; } } pthread_mutex_unlock(&pwdb_lock); } /* owner write needs to be super-user or me only */ if ((s.st_mode & S_IWUSR) != 0 && (s.st_uid != 0 && s.st_uid != myuid)) { if (err != NULL) { snprintf(err, errlen, "%s is writeable and owned by uid %u which is not the executing uid (%u)%s", path, s.st_uid, myuid, myuid != 0 ? " or the superuser" : ""); } return 0; } /* if nobody else can execute below here, that's good enough */ if ((s.st_mode & (S_IXGRP|S_IXOTH)) == 0) { *ino = (ino_t) -1; return 1; } } return 1; } /* ** DKIMF_SECUREFILE -- determine whether a file at a specific path is "safe" ** ** Parameters: ** path -- path to evaluate ** ino -- inode of evaluated object ** myuid -- user to impersonate (-1 means "me") ** err -- error buffer ** errlen -- bytes available at "err" ** ** Return value: ** As for dkimf_checkfsnode(). ** ** Notes: ** If realpath() is available, this function checks the entire resolved ** filesystem tree from the root to the target file to ensure there are no ** permissions that would allow someone else on the system to either read ** or replace the file being evaluated. (It's designed to check private ** key files.) Without realpath(), only the target filename is checked. */ int dkimf_securefile(const char *path, ino_t *ino, uid_t myuid, char *err, size_t errlen) { int status; struct passwd *pw; #ifdef HAVE_REALPATH char *p; char *q; char real[MAXPATHLEN + 1]; char partial[MAXPATHLEN + 1]; char myname[BUFRSZ + 1]; #endif /* HAVE_REALPATH */ assert(path != NULL); assert(ino != NULL); /* figure out who I am */ pthread_mutex_lock(&pwdb_lock); if (myuid == (uid_t) -1) pw = getpwuid(geteuid()); else pw = getpwuid(myuid); if (pw == NULL) { pthread_mutex_unlock(&pwdb_lock); return -1; } if (myuid == (uid_t) -1) myuid = pw->pw_uid; #ifdef HAVE_REALPATH strlcpy(myname, pw->pw_name, sizeof myname); pthread_mutex_unlock(&pwdb_lock); p = realpath(path, real); if (p == NULL) return -1; /* ** Check each node in the tree to ensure that: ** 1) The file itself is read-write only by the executing user and the ** super-user; ** 2) No directory above the file is writeable by anyone other than ** the executing user and the super-user. */ partial[0] = '/'; partial[1] = '\0'; # ifdef HAVE_STRSEP q = real; while ((p = strsep(&q, "/")) != NULL) # else /* HAVE_STRSEP */ q = NULL; for (p = strtok_r(real, "/", &q); p != NULL; p = strtok_r(NULL, "/", &q)) # endif /* HAVE_STRSEP */ { strlcat(partial, p, sizeof partial); status = dkimf_checkfsnode((const char *) partial, myuid, myname, ino, err, errlen); if (status != 1) return status; if (partial[1] != '\0') strlcat(partial, "/", sizeof partial); } return 1; #else /* HAVE_REALPATH */ struct stat s; pthread_mutex_unlock(&pwdb_lock); status = stat(path, &s); if (status != 0) return -1; /* we don't own it and neither does the super-user; bad */ if (s.st_uid != myuid && s.st_uid != 0) return 0; /* world readable/writeable; bad */ if ((s.st_node & (S_IROTH|S_IWOTH)) != 0) return 0; /* group read/write is bad if others are in that group */ if ((s.st_mode & (S_IRGRP|S_IWGRP)) != 0) { int c; struct group *gr; /* get the file's group entry */ pthread_mutex_lock(&pwdb_lock); gr = getgrgid(s.st_gid); if (gr == NULL) { pthread_mutex_unlock(&pwdb_lock); return -1; } for (c = 0; gr->gr_mem[c] != NULL; c++) { if (strcmp(gr->gr_mem[c], pw->pw_name) != 0) { pthread_mutex_unlock(&pwdb_lock); return 0; } } setpwent(); while (pw = getpwent(); pw != NULL; pw = getpwent()) { if (pw->pw_uid != myuid && pw->pw_gid == s.st_gid) { pthread_mutex_unlock(&pwdb_lock); return 0; } } endpwent(); pthread_mutex_unlock(&pwdb_lock); } /* guess we're okay... */ *ino = s.st_ino; return 1; #endif /* HAVE_REALPATH */ } /* ** DKIMF_LOADKEY -- resolve a key ** ** Parameters: ** buf -- key buffer ** buflen -- pointer to key buffer's length (updated) ** insecure -- key is insecure (returned) ** error -- buffer to receive error string ** errlen -- bytes available at "error" ** ** Return value: ** TRUE on successful load, false otherwise. ** ** Notes: ** The caller might pass a key or a filename in "buf". If we think it's a ** filename, replace the contents of "buf" with what we find in that file. */ static _Bool dkimf_loadkey(char *buf, size_t *buflen, _Bool *insecure, char *error, size_t errlen) { ino_t ino; assert(buf != NULL); assert(buflen != NULL); if (buf[0] == '/' || (buf[0] == '.' && buf[1] == '/') || (buf[0] == '.' && buf[1] == '.' && buf[2] == '/')) { int fd; int status; ssize_t rlen; struct stat s; fd = open(buf, O_RDONLY); if (fd < 0) { if (error != NULL) strlcpy(error, strerror(errno), errlen); return FALSE; } status = fstat(fd, &s); if (status != 0 || !S_ISREG(s.st_mode)) { if (error != NULL) { if (!S_ISREG(s.st_mode)) { strlcpy(error, "Not a regular file", errlen); } else { strlcpy(error, strerror(errno), errlen); } } close(fd); return FALSE; } if (!dkimf_securefile(buf, &ino, (uid_t) -1, error, errlen) || (ino != (ino_t) -1 && ino != s.st_ino)) *insecure = TRUE; else *insecure = FALSE; *buflen = MIN(s.st_size, *buflen); rlen = read(fd, buf, *buflen); close(fd); if (rlen < *buflen) return FALSE; } return TRUE; } /* ** DKIMF_ADD_SIGNREQUEST -- add a signing request ** ** Parameters: ** dfc -- message context ** keytable -- table from which to get key ** keyname -- name of private key to use ** signer -- signer identity to use ** signlen -- signature length ** ** Return value: ** 3 -- substitution token provided but domain not provided ** 2 -- requested key could not be loaded ** 1 -- requested key not found ** 0 -- requested key added ** -1 -- requested key found but add failed (memory? or format) */ static int dkimf_add_signrequest(struct msgctx *dfc, DKIMF_DB keytable, char *keyname, char *signer, ssize_t signlen) { _Bool found = FALSE; size_t keydatasz = 0; struct signreq *new; struct dkimf_db_data dbd[3]; char keydata[MAXBUFRSZ + 1]; char domain[DKIM_MAXHOSTNAMELEN + 1]; char selector[BUFRSZ + 1]; char err[BUFRSZ + 1]; assert(dfc != NULL); /* ** Error out if we want the default key but the key or selector were ** not provided. */ if (keyname == NULL) { if (curconf->conf_seckey == NULL || curconf->conf_selector == NULL) return 1; } if (keytable != NULL) { _Bool insecure; assert(keyname != NULL); memset(domain, '\0', sizeof domain); memset(selector, '\0', sizeof selector); memset(keydata, '\0', sizeof keydata); dbd[0].dbdata_buffer = domain; dbd[0].dbdata_buflen = sizeof domain - 1; dbd[0].dbdata_flags = DKIMF_DB_DATA_OPTIONAL; dbd[1].dbdata_buffer = selector; dbd[1].dbdata_buflen = sizeof selector - 1; dbd[1].dbdata_flags = DKIMF_DB_DATA_OPTIONAL; dbd[2].dbdata_buffer = keydata; dbd[2].dbdata_buflen = sizeof keydata - 1; dbd[2].dbdata_flags = DKIMF_DB_DATA_OPTIONAL; if (dkimf_db_get(keytable, keyname, strlen(keyname), dbd, 3, &found) != 0) { memset(err, '\0', sizeof err); (void) dkimf_db_strerror(keytable, err, sizeof err); if (dolog) { if (err[0] != '\0') { syslog(LOG_ERR, "key '%s': dkimf_db_get(): %s", keyname, err); } else { syslog(LOG_ERR, "key '%s': dkimf_db_get() failed", keyname); } } return -1; } if (!found) return 1; if (dbd[0].dbdata_buflen == 0 || dbd[0].dbdata_buflen == (size_t) -1 || dbd[1].dbdata_buflen == 0 || dbd[1].dbdata_buflen == (size_t) -1 || dbd[2].dbdata_buflen == 0 || dbd[2].dbdata_buflen == (size_t) -1) { if (dolog) { syslog(LOG_ERR, "KeyTable entry for '%s' corrupt", keyname); } return 2; } if (domain[0] == '%' && domain[1] == '\0' && dfc->mctx_domain == NULL) { if (dolog) { syslog(LOG_ERR, "KeyTable entry for '%s' cannot be resolved", keyname); } return 3; } if (keydata[0] == '/') { char *d; char tmpdata[MAXBUFRSZ + 1]; memset(tmpdata, '\0', sizeof tmpdata); if (domain[0] == '%' && domain[1] == '\0') d = dfc->mctx_domain; else d = domain; dkimf_reptoken(tmpdata, sizeof tmpdata, keydata, d); memcpy(keydata, tmpdata, sizeof keydata); } keydatasz = sizeof keydata - 1; insecure = FALSE; if (!dkimf_loadkey(dbd[2].dbdata_buffer, &keydatasz, &insecure, err, sizeof err)) { if (dolog) { syslog(LOG_ERR, "can't load key from %s: %s", dbd[2].dbdata_buffer, err); } return 2; } if (insecure) { if (dolog) { int sev; sev = (curconf->conf_safekeys ? LOG_ERR : LOG_WARNING); syslog(sev, "%s: key data is not secure: %s", keyname, err); } if (curconf->conf_safekeys) return 2; } } new = malloc(sizeof *new); if (new == NULL) return -1; new->srq_next = NULL; new->srq_dkim = NULL; new->srq_domain = NULL; new->srq_selector = NULL; new->srq_keydata = NULL; new->srq_signlen = signlen; if (signer != NULL && signer[0] != '\0') new->srq_signer = (u_char *) strdup(signer); else new->srq_signer = NULL; if (keytable != NULL) { if (domain[0] == '%' && domain[1] == '\0') new->srq_domain = (u_char *) strdup((char *) dfc->mctx_domain); else new->srq_domain = (u_char *) strdup((char *) domain); new->srq_selector = (u_char *) strdup((char *) selector); new->srq_keydata = (void *) malloc(keydatasz + 1); if (new->srq_keydata == NULL) { free(new); return -1; } memset(new->srq_keydata, '\0', keydatasz + 1); memcpy(new->srq_keydata, dbd[2].dbdata_buffer, keydatasz); } if (dfc->mctx_srtail != NULL) dfc->mctx_srtail->srq_next = new; else dfc->mctx_srtail = new; if (dfc->mctx_srhead == NULL) dfc->mctx_srhead = new; return 0; } /* ** DKIMF_MSR_HEADER -- process headers for multiple signing requests ** ** Parameters: ** srh -- head of the signature request list ** last -- last handle processed (returned on error) ** header -- header field name and value ** headerlen -- number of bytes at "header" ** ** Return value: ** A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed ** or some other constant if one of them failed. */ static DKIM_STAT dkimf_msr_header(struct signreq *sr, DKIM **last, u_char *header, size_t headerlen) { DKIM_STAT status; assert(sr != NULL); assert(header != NULL); while (sr != NULL) { status = dkim_header(sr->srq_dkim, header, headerlen); if (status != DKIM_STAT_OK) { if (last != NULL) *last = sr->srq_dkim; return status; } sr = sr->srq_next; } return DKIM_STAT_OK; } /* ** DKIMF_MSR_EOH -- process end-of-headers for multiple signing requests ** ** Parameters: ** srh -- head of the signature request list ** last -- last DKIM handle processed (returned on error) ** ** Return value: ** A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed ** or some other constant if one of them failed. */ static DKIM_STAT dkimf_msr_eoh(struct signreq *sr, DKIM **last) { DKIM_STAT status; assert(sr != NULL); while (sr != NULL) { status = dkim_eoh(sr->srq_dkim); if (status != DKIM_STAT_OK) { if (last != NULL) *last = sr->srq_dkim; return status; } sr = sr->srq_next; } return DKIM_STAT_OK; } /* ** DKIMF_MSR_BODY -- process a body chunk for multiple signing requests ** ** Parameters: ** srh -- head of the signature request list ** last -- last DKIM handle processed (returned on error) ** body -- body chunk ** bodylen -- body length ** ** Return value: ** A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed ** or some other constant if one of them failed. */ static DKIM_STAT dkimf_msr_body(struct signreq *sr, DKIM **last, u_char *body, size_t bodylen) { DKIM_STAT status; assert(sr != NULL); assert(body != NULL); while (sr != NULL) { status = dkim_body(sr->srq_dkim, body, bodylen); if (status != DKIM_STAT_OK) { if (last != NULL) *last = sr->srq_dkim; return status; } sr = sr->srq_next; } return DKIM_STAT_OK; } /* ** DKIMF_MSR_MINBODY -- determine minimum body required to satisfy all ** open canonicalizations ** ** Parameters: ** srh -- head of the signature request list ** ** Return value: ** Maximum of all dkim_minbody() returns. */ static int dkimf_msr_minbody(struct signreq *sr) { u_long mb = 0; u_long ret = 0; assert(sr != NULL); while (sr != NULL) { ret = dkim_minbody(sr->srq_dkim); if (ret > mb) mb = ret; sr = sr->srq_next; } return mb;; } /* ** DKIMF_MSR_EOM -- process end-of-message for multiple signing requests ** ** Parameters: ** srh -- head of the signature request list ** last -- last DKIM handle processed (returned) ** ** Return value: ** A DKIM_STAT_* constant, either DKIM_STAT_OK if all of them passed ** or some other constant if one of them failed. */ static DKIM_STAT dkimf_msr_eom(struct signreq *sr, DKIM **last) { _Bool testkey; DKIM_STAT status; assert(sr != NULL); while (sr != NULL) { status = dkim_eom(sr->srq_dkim, &testkey); if (status != DKIM_STAT_OK) { if (last != NULL) *last = sr->srq_dkim; return status; } sr = sr->srq_next; } return DKIM_STAT_OK; } /* ** DKIMF_PRESCREEN -- check signatures against third-party limitations ** ** Parameters: ** dkim -- DKIM handle ** sigs -- array of signatures ** nsigs -- size of signature array ** ** Return value: ** DKIM_CBSTAT_CONTINUE */ static DKIM_CBSTAT dkimf_prescreen(DKIM *dkim, DKIM_SIGINFO **sigs, int nsigs) { int c; unsigned int ni = 0; u_char *domain; u_char *sdomain; SMFICTX *ctx; connctx cc; msgctx dfc; struct dkimf_config *conf; ctx = (SMFICTX *) dkim_get_user_context(dkim); cc = (connctx) dkimf_getpriv(ctx); conf = cc->cctx_config; dfc = cc->cctx_msg; domain = dkim_getdomain(dkim); if (conf->conf_maxverify > 0) { int n; _Bool *ig = NULL; ig = (_Bool *) malloc(sizeof(_Bool) * nsigs); if (ig == NULL) return DKIM_CBSTAT_ERROR; /* mark everything to be ignored */ for (c = 0; c < nsigs; c++) ig[c] = TRUE; n = conf->conf_maxverify; if (conf->conf_thirdpartydb != NULL) { _Bool found; /* unmark sigs that are explicitly trusted */ for (c = 0; c < nsigs; c++) { sdomain = dkim_sig_getdomain(sigs[c]); found = FALSE; if (dkimf_db_get(conf->conf_thirdpartydb, (char *) sdomain, 0, NULL, 0, &found) != 0) { free(ig); return DKIM_CBSTAT_ERROR; } if (found) { ig[c] = FALSE; n--; } } } /* unmark from the top down any that don't exceed the limit */ for (c = 0; c < nsigs && n > 0; c++) { if (ig[c]) { n--; ig[c] = FALSE; } } /* mark what's left to be ignored */ for (c = 0; c < nsigs; c++) { if (ig[c]) { dkim_sig_ignore(sigs[c]); ni++; } } if (conf->conf_dolog && ni > 0) { syslog(LOG_INFO, "%s: ignoring %u signature%s", dkim_getid(dkim), ni, ni == 1 ? "" : "s"); } free(ig); return DKIM_CBSTAT_CONTINUE; } /* ignore signatures which are neither first-party nor trusted */ for (c = 0; c < nsigs; c++) { sdomain = dkim_sig_getdomain(sigs[c]); /* author domain */ if (strcasecmp((char *) sdomain, (char *) domain) == 0) continue; /* trusted third party domain */ if (conf->conf_thirdpartydb != NULL) { _Bool found = FALSE; if (dkimf_db_get(conf->conf_thirdpartydb, (char *) sdomain, 0, NULL, 0, &found) != 0) return DKIM_CBSTAT_ERROR; if (found) continue; } /* neither; arrange to ignore it */ dkim_sig_ignore(sigs[c]); if (conf->conf_dolog) { syslog(LOG_INFO, "%s: ignoring signature from %s", dfc->mctx_jobid, sdomain); } } return DKIM_CBSTAT_CONTINUE; } /* ** DKIMF_ARFTYPE -- return ARF message type to report ** ** Parameters: ** dfc -- DKIM filter context ** ** Return value: ** An ARF_TYPE_* constant. */ static int dkimf_arftype(msgctx dfc) { assert(dfc != NULL); if (dfc->mctx_susp) return ARF_TYPE_FRAUD; else return ARF_TYPE_AUTHFAIL; } /* ** DKIMF_ARFDKIM -- return an appropriate ARF DKIM failure code ** ** Parameters: ** dfc -- DKIM filter context ** ** Return value: ** An ARF_DKIMF_* constant. */ static int dkimf_arfdkim(msgctx dfc) { DKIM_SIGINFO *sig; assert(dfc != NULL); sig = dkim_getsignature(dfc->mctx_dkimv); if (sig == NULL) return ARF_DKIMF_UNKNOWN; if (dkim_sig_getbh(sig) == DKIM_SIGBH_MISMATCH) return ARF_DKIMF_BODYHASH; switch (dkim_sig_geterror(sig)) { case DKIM_SIGERROR_BADSIG: return ARF_DKIMF_SIGNATURE; case DKIM_SIGERROR_KEYREVOKED: return ARF_DKIMF_REVOKED; case DKIM_SIGERROR_VERSION: case DKIM_SIGERROR_INVALID_HC: case DKIM_SIGERROR_INVALID_BC: case DKIM_SIGERROR_MISSING_A: case DKIM_SIGERROR_INVALID_A: case DKIM_SIGERROR_MISSING_H: case DKIM_SIGERROR_INVALID_L: case DKIM_SIGERROR_INVALID_Q: case DKIM_SIGERROR_INVALID_QO: case DKIM_SIGERROR_MISSING_D: case DKIM_SIGERROR_EMPTY_D: case DKIM_SIGERROR_MISSING_S: case DKIM_SIGERROR_EMPTY_S: case DKIM_SIGERROR_MISSING_B: case DKIM_SIGERROR_EMPTY_B: case DKIM_SIGERROR_CORRUPT_B: case DKIM_SIGERROR_DNSSYNTAX: case DKIM_SIGERROR_MISSING_BH: case DKIM_SIGERROR_EMPTY_BH: case DKIM_SIGERROR_CORRUPT_BH: case DKIM_SIGERROR_MULTIREPLY: case DKIM_SIGERROR_EMPTY_H: case DKIM_SIGERROR_INVALID_H: case DKIM_SIGERROR_TOOLARGE_L: case DKIM_SIGERROR_KEYVERSION: case DKIM_SIGERROR_KEYUNKNOWNHASH: case DKIM_SIGERROR_KEYTYPEMISSING: case DKIM_SIGERROR_KEYTYPEUNKNOWN: return ARF_DKIMF_SYNTAX; default: return ARF_DKIMF_OTHER; } } /* ** DKIMF_REPORTADDR -- set reporting address ** ** Parameters: ** conf -- current configuration ** ** Return value: ** None. */ static void dkimf_reportaddr(struct dkimf_config *conf) { uid_t uid; struct passwd *pw; assert(conf != NULL); if (conf->conf_reportaddr != NULL) { int status; u_char *user; u_char *domain; u_char env[MAXADDRESS + 1]; /* reporting address */ strlcpy(reportaddr, conf->conf_reportaddr, sizeof reportaddr); strlcpy((char *) env, conf->conf_reportaddr, sizeof reportaddr); status = dkim_mail_parse(env, &user, &domain); if (status == 0 && user != NULL && domain != NULL) { snprintf(reportcmd, sizeof reportcmd, "%s -t -f%s@%s", conf->conf_mtacommand, user, domain); return; } else { if (dolog) { syslog(LOG_ERR, "error parsing ReportAddress; using default"); } } } /* not successful case has already returned. Make up a value if not * set of an error occurs */ uid = geteuid(); pw = getpwuid(uid); if (pw == NULL) { snprintf(reportaddr, sizeof reportaddr, "%u@%s", uid, myhostname); } else { snprintf(reportaddr, sizeof reportaddr, "%s@%s", pw->pw_name, myhostname); } snprintf(reportcmd, sizeof reportcmd, "%s -t -f%s", conf->conf_mtacommand, reportaddr); } /* ** DKIMF_LOOKUP_STRTOINT -- look up the integer code for a config option ** or value ** ** Parameters: ** opt -- option to look up ** table -- lookup table to use ** ** Return value: ** Integer version of the option, or -1 on error. */ static int dkimf_lookup_strtoint(char *opt, struct lookup *table) { int c; for (c = 0; ; c++) { if (table[c].str == NULL || strcasecmp(opt, table[c].str) == 0) return table[c].code; } } /* ** DKIMF_LOOKUP_INTTOSTR -- look up the string matching an internal code ** ** Parameters: ** code -- code to look up ** table -- lookup table to use ** ** Return value: ** String version of the option, or NULL on error. */ static const char * dkimf_lookup_inttostr(int code, struct lookup *table) { int c; for (c = 0; ; c++) { if (table[c].code == -1 || table[c].code == code) return table[c].str; } assert(0); /* NOTREACHED */ } /* ** DKIMF_GETDKIM -- retrieve DKIM handle in use ** ** Parameters: ** vp -- opaque pointer (from test.c) ** ** Return value: ** DKIM handle in use, or NULL. */ DKIM * dkimf_getdkim(void *vp) { struct connctx *cc; assert(vp != NULL); cc = vp; if (cc->cctx_msg != NULL) return cc->cctx_msg->mctx_dkimv; else return NULL; } /* ** DKIMF_GETSRLIST -- retrieve signing request list ** ** Parameters: ** vp -- opaque pointer (from test.c) ** ** Return value: ** Head of the signing request list. */ struct signreq * dkimf_getsrlist(void *vp) { struct connctx *cc; assert(vp != NULL); cc = vp; if (cc->cctx_msg != NULL) return cc->cctx_msg->mctx_srhead; else return NULL; } /* ** DKIMF_SIGHANDLER -- signal handler ** ** Parameters: ** sig -- signal received ** ** Return value: ** None. */ static void dkimf_sighandler(int sig) { if (sig == SIGINT || sig == SIGTERM || sig == SIGHUP) { diesig = sig; die = TRUE; } else if (sig == SIGUSR1 && !die) { if (conffile != NULL) reload = TRUE; } } /* ** DKIMF_RELOADER -- reload signal thread ** ** Parameters: ** vp -- void pointer required by thread API but not used ** ** Return value: ** NULL. */ static void * dkimf_reloader(/* UNUSED */ void *vp) { int sig; sigset_t mask; (void) pthread_detach(pthread_self()); sigemptyset(&mask); sigaddset(&mask, SIGUSR1); while (!die) { (void) sigwait(&mask, &sig); if (conffile != NULL) reload = TRUE; } return NULL; } /* ** DKIMF_KILLCHILD -- kill child process ** ** Parameters: ** pid -- process ID to signal ** sig -- signal to use ** dolog -- log it? ** ** Return value: ** None. */ static void dkimf_killchild(pid_t pid, int sig, _Bool dolog) { if (kill(pid, sig) == -1 && dolog) { syslog(LOG_ERR, "kill(%d, %d): %s", pid, sig, strerror(errno)); } } /* ** DKIMF_ZAPKEY -- clobber the copy of the private key ** ** Parameters: ** conf -- configuration handle in which to clobber the key ** ** Return value: ** None. */ static void dkimf_zapkey(struct dkimf_config *conf) { assert(conf != NULL); if (conf->conf_seckey != NULL) { memset(conf->conf_seckey, '\0', conf->conf_keylen); free(conf->conf_seckey); conf->conf_seckey = NULL; } } /* ** DKIMF_AUTHORSIGOK -- return TRUE iff a message was signed with an ** author signature that passed ** ** Parameters: ** msg -- a message context handle ** ** Return value: ** TRUE iff the message referenced by "dkim" was signed with an ** author signature and that signature passed. */ static _Bool dkimf_authorsigok(msgctx msg) { DKIM_STAT status; int c; int nsigs; DKIM_SIGINFO **sigs; assert(msg != NULL); status = dkim_getsiglist(msg->mctx_dkimv, &sigs, &nsigs); if (status != DKIM_STAT_OK) return FALSE; for (c = 0; c < nsigs; c++) { /* skip signatures with errors */ if (dkim_sig_geterror(sigs[c]) != DKIM_SIGERROR_UNKNOWN && dkim_sig_geterror(sigs[c]) != DKIM_SIGERROR_OK) continue; if (strcasecmp((char *) dkim_sig_getdomain(sigs[c]), (char *) msg->mctx_domain) == 0 && (dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0 && dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH) return TRUE; } return FALSE; } /* ** DKIMF_CONFIG_NEW -- get a new configuration handle ** ** Parameters: ** None. ** ** Return value: ** A new configuration handle, or NULL on error. */ static struct dkimf_config * dkimf_config_new(void) { struct dkimf_config *new; new = (struct dkimf_config *) malloc(sizeof(struct dkimf_config)); if (new == NULL) return NULL; memset(new, '\0', sizeof(struct dkimf_config)); new->conf_hdrcanon = DKIM_CANON_DEFAULT; new->conf_bodycanon = DKIM_CANON_DEFAULT; new->conf_dnstimeout = DEFTIMEOUT; new->conf_maxverify = DEFMAXVERIFY; new->conf_maxhdrsz = DEFMAXHDRSZ; new->conf_signbytes = -1L; new->conf_sigmintype = SIGMIN_BYTES; #ifdef _FFR_REPUTATION new->conf_repfactor = DKIMF_REP_DEFFACTOR; new->conf_repcachettl = DKIMF_REP_DEFCACHETTL; #endif /* _FFR_REPUTATION */ new->conf_safekeys = TRUE; #ifdef _FFR_STATS new->conf_reporthost = myhostname; #endif /* _FFR_STATS */ #ifdef _FFR_RATE_LIMIT new->conf_flowdatattl = DEFFLOWDATATTL; new->conf_flowfactor = 1; #endif /* _FFR_RATE_LIMIT */ new->conf_mtacommand = SENDMAIL_PATH; #ifdef _FFR_ATPS new->conf_atpshash = dkimf_atpshash[0].str; #endif /* _FFR_ATPS */ new->conf_selectcanonhdr = SELECTCANONHDR; memcpy(&new->conf_handling, &defaults, sizeof new->conf_handling); return new; } /* ** DKIMF_CONFIG_FREE -- destroy a configuration handle ** ** Parameters: ** conf -- pointer to the configuration handle to be destroyed ** ** Return value: ** None. */ static void dkimf_config_free(struct dkimf_config *conf) { assert(conf != NULL); assert(conf->conf_refcnt == 0); dkimf_zapkey(conf); if (conf->conf_libopendkim != NULL) dkim_close(conf->conf_libopendkim); if (conf->conf_testdnsdb != NULL) dkimf_db_close(conf->conf_testdnsdb); if (conf->conf_domainsdb != NULL) dkimf_db_close(conf->conf_domainsdb); if (conf->conf_bldb != NULL) dkimf_db_close(conf->conf_bldb); if (conf->conf_domlist != NULL) free(conf->conf_domlist); if (conf->conf_omithdrdb != NULL) dkimf_db_close(conf->conf_omithdrdb); if (conf->conf_thirdpartydb != NULL) dkimf_db_close(conf->conf_thirdpartydb); if (conf->conf_signhdrsdb != NULL) dkimf_db_close(conf->conf_signhdrsdb); if (conf->conf_senderhdrsdb != NULL) dkimf_db_close(conf->conf_senderhdrsdb); if (conf->conf_oversigndb != NULL) dkimf_db_close(conf->conf_oversigndb); if (conf->conf_mtasdb != NULL) dkimf_db_close(conf->conf_mtasdb); if (conf->conf_macrosdb != NULL) dkimf_db_close(conf->conf_macrosdb); if (conf->conf_mbsdb != NULL) dkimf_db_close(conf->conf_mbsdb); if (conf->conf_dontsigntodb != NULL) dkimf_db_close(conf->conf_dontsigntodb); #ifdef _FFR_ATPS if (conf->conf_atpsdb != NULL) dkimf_db_close(conf->conf_atpsdb); #endif /* _FFR_ATPS */ if (conf->conf_authservid != NULL) free(conf->conf_authservid); if (conf->conf_peerdb != NULL) dkimf_db_close(conf->conf_peerdb); if (conf->conf_internal != NULL) dkimf_db_close(conf->conf_internal); if (conf->conf_exignore != NULL) dkimf_db_close(conf->conf_exignore); if (conf->conf_exemptdb != NULL) dkimf_db_close(conf->conf_exemptdb); #ifdef _FFR_REPLACE_RULES if (conf->conf_replist != NULL) dkimf_free_replist(conf->conf_replist); if (conf->conf_rephdrsdb != NULL) dkimf_db_close(conf->conf_rephdrsdb); #endif /* _FFR_REPLACE_RULES */ #ifdef _FFR_VBR if (conf->conf_vbr_trusteddb != NULL) dkimf_db_close(conf->conf_vbr_trusteddb); #endif /* _FFR_VBR */ if (conf->conf_nosignpats != NULL) { int n; for (n = 0; conf->conf_nosignpats[n] != NULL; n++) regfree(conf->conf_nosignpats[n]); free(conf->conf_nosignpats); } #ifdef _FFR_RESIGN if (conf->conf_resigndb != NULL) dkimf_db_close(conf->conf_resigndb); #endif /* _FFR_RESIGN */ #ifdef _FFR_CONDITIONAL if (conf->conf_conditionaldb != NULL) dkimf_db_close(conf->conf_conditionaldb); #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_RATE_LIMIT if (conf->conf_ratelimitdb != NULL) dkimf_db_close(conf->conf_ratelimitdb); if (conf->conf_flowdatadb != NULL) dkimf_db_close(conf->conf_flowdatadb); #endif /* _FFR_RATE_LIMIT */ #ifdef _FFR_REPUTATION if (conf->conf_repratiosdb != NULL) dkimf_db_close(conf->conf_repratiosdb); if (conf->conf_replimitsdb != NULL) dkimf_db_close(conf->conf_replimitsdb); if (conf->conf_replimitmodsdb != NULL) dkimf_db_close(conf->conf_replimitmodsdb); if (conf->conf_repspamcheck != NULL) regfree(&conf->conf_repspamre); if (conf->conf_rep != NULL) dkimf_rep_close(conf->conf_rep); #endif /* _FFR_REPUTATION */ #ifdef _FFR_REPRRD if (conf->conf_reprrd != NULL) reprrd_close(conf->conf_reprrd); #endif /* _FFR_REPRRD */ #ifdef USE_LUA if (conf->conf_setupscript != NULL) free(conf->conf_setupscript); if (conf->conf_setupfunc != NULL) free(conf->conf_setupfunc); if (conf->conf_screenscript != NULL) free(conf->conf_screenscript); if (conf->conf_screenfunc != NULL) free(conf->conf_screenfunc); # ifdef _FFR_STATSEXT if (conf->conf_statsscript != NULL) free(conf->conf_statsscript); if (conf->conf_statsfunc != NULL) free(conf->conf_statsfunc); # endif /* _FFR_STATSEXT */ if (conf->conf_finalscript != NULL) free(conf->conf_finalscript); if (conf->conf_finalfunc != NULL) free(conf->conf_finalfunc); #endif /* USE_LUA */ if (conf->conf_keytabledb != NULL) dkimf_db_close(conf->conf_keytabledb); if (conf->conf_signtabledb != NULL) dkimf_db_close(conf->conf_signtabledb); if (conf->conf_data != NULL) config_free(conf->conf_data); free(conf); } /* ** DKIMF_PARSEHANDLER -- parse a handler ** ** Parameters: ** cfg -- configuration data structure to check ** name -- handler name ** hndl -- handler structure to update ** err -- error buffer ** errlen -- bytes available at "err" ** ** Return value: ** TRUE if no error, FALSE if error. */ static _Bool dkimf_parsehandler(struct config *cfg, char *name, struct handling *hndl, char *err, size_t errlen) { int action; char *val = NULL; assert(name != NULL); assert(strncasecmp(name, "on-", 3) == 0); assert(hndl != NULL); assert(err != NULL); if (cfg == NULL) return TRUE; (void) config_get(cfg, name, &val, sizeof val); if (val == NULL) return TRUE; action = dkimf_lookup_strtoint(val, dkimf_values); if (action == -1) { snprintf(err, errlen, "invalid handling value \"%s\"", val); return -1; } switch (dkimf_lookup_strtoint(name + 3, dkimf_params)) { case HNDL_DEFAULT: hndl->hndl_nosig = action; hndl->hndl_badsig = action; hndl->hndl_dnserr = action; hndl->hndl_internal = action; hndl->hndl_security = action; hndl->hndl_nokey = action; #if defined(_FFR_REPUTATION) || defined(_FFR_REPRRD) hndl->hndl_reperr = action; #endif /* _FFR_REPUTATION || defined(_FFR_REPRRD) */ hndl->hndl_siggen = action; return TRUE; case HNDL_NOSIGNATURE: hndl->hndl_nosig = action; return TRUE; case HNDL_BADSIGNATURE: hndl->hndl_badsig = action; return TRUE; case HNDL_DNSERROR: hndl->hndl_dnserr = action; return TRUE; case HNDL_INTERNAL: hndl->hndl_internal = action; return TRUE; case HNDL_SECURITY: hndl->hndl_security = action; return TRUE; case HNDL_NOKEY: hndl->hndl_nokey = action; return TRUE; #if defined(_FFR_REPUTATION) || defined(_FFR_REPRRD) case HNDL_REPERROR: hndl->hndl_reperr = action; return TRUE; #endif /* _FFR_REPUTATION || defined(_FFR_REPRRD) */ case HNDL_SIGGEN: hndl->hndl_siggen = action; return TRUE; default: snprintf(err, errlen, "unknown handling key \"%s\"", name); return FALSE; } } /* ** DKIMF_CONFIG_LOAD -- load a configuration handle based on file content ** ** Paramters: ** data -- configuration data loaded from config file ** conf -- configuration structure to load ** err -- where to write errors ** errlen -- bytes available at "err" ** become -- pretend we're the named user (can be NULL) ** ** Return value: ** 0 -- success ** !0 -- error ** ** Side effects: ** openlog() may be called by this function */ static int dkimf_config_load(struct config *data, struct dkimf_config *conf, char *err, size_t errlen, char *become) { #ifdef USE_LDAP _Bool btmp; #endif /* USE_LDAP */ int maxsign; int dbflags = 0; char *str; char confstr[BUFRSZ + 1]; char basedir[MAXPATHLEN + 1]; assert(conf != NULL); assert(err != NULL); memset(basedir, '\0', sizeof basedir); memset(confstr, '\0', sizeof confstr); if (data != NULL) { int tmpint; #if (USE_LDAP || USE_ODBX) (void) config_get(data, "SoftStart", &conf->conf_softstart, sizeof conf->conf_softstart); #endif /* (USE_LDAP || USE_ODBX) */ (void) config_get(data, "DNSConnect", &conf->conf_dnsconnect, sizeof conf->conf_dnsconnect); (void) config_get(data, "ResolverTracing", &conf->conf_restrace, sizeof conf->conf_restrace); (void) config_get(data, "AlwaysAddARHeader", &conf->conf_alwaysaddar, sizeof conf->conf_alwaysaddar); str = NULL; (void) config_get(data, "AuthservID", &str, sizeof str); if (str != NULL) { if (strcmp(str, "HOSTNAME") == 0) conf->conf_authservid = strdup(myhostname); else conf->conf_authservid = strdup(str); } (void) config_get(data, "AuthservIDWithJobID", &conf->conf_authservidwithjobid, sizeof conf->conf_authservidwithjobid); #ifdef HAVE_CURL_EASY_STRERROR (void) config_get(data, "SMTPURI", &conf->conf_smtpuri, sizeof conf->conf_smtpuri); #endif /* HAVE_CURL_EASY_STRERROR */ str = NULL; (void) config_get(data, "BaseDirectory", &str, sizeof str); if (str != NULL) strlcpy(basedir, str, sizeof basedir); if (conf->conf_canonstr == NULL) { (void) config_get(data, "Canonicalization", &conf->conf_canonstr, sizeof conf->conf_canonstr); } (void) config_get(data, "ClockDrift", &conf->conf_clockdrift, sizeof conf->conf_clockdrift); #ifdef _FFR_DEFAULT_SENDER (void) config_get(data, "DefaultSender", &conf->conf_defsender, sizeof conf->conf_defsender); #endif /* _FFR_DEFAULT_SENDER */ (void) config_get(data, "Diagnostics", &conf->conf_ztags, sizeof conf->conf_ztags); (void) config_get(data, "DiagnosticDirectory", &conf->conf_diagdir, sizeof conf->conf_diagdir); (void) config_get(data, "RedirectFailuresTo", &conf->conf_redirect, sizeof conf->conf_redirect); #ifdef _FFR_RESIGN (void) config_get(data, "ResignMailTo", &conf->conf_resign, sizeof conf->conf_resign); (void) config_get(data, "ResignAll", &conf->conf_resignall, sizeof conf->conf_resignall); #endif /* _FFR_RESIGN */ if (conf->conf_dnstimeout == DEFTIMEOUT) { (void) config_get(data, "DNSTimeout", &conf->conf_dnstimeout, sizeof conf->conf_dnstimeout); } (void) config_get(data, "EnableCoredumps", &conf->conf_enablecores, sizeof conf->conf_enablecores); (void) config_get(data, "MinimumKeyBits", &conf->conf_minkeybits, sizeof conf->conf_minkeybits); (void) config_get(data, "RequestReports", &conf->conf_reqreports, sizeof conf->conf_reqreports); (void) config_get(data, "RequireSafeKeys", &conf->conf_safekeys, sizeof conf->conf_safekeys); (void) config_get(data, "TestDNSData", &conf->conf_testdnsdata, sizeof conf->conf_testdnsdata); (void) config_get(data, "NoHeaderB", &conf->conf_noheaderb, sizeof conf->conf_noheaderb); (void) config_get(data, "FixCRLF", &conf->conf_fixcrlf, sizeof conf->conf_fixcrlf); (void) config_get(data, "KeepTemporaryFiles", &conf->conf_keeptmpfiles, sizeof conf->conf_keeptmpfiles); (void) config_get(data, "StrictHeaders", &conf->conf_stricthdrs, sizeof conf->conf_stricthdrs); (void) config_get(data, "TemporaryDirectory", &conf->conf_tmpdir, sizeof conf->conf_tmpdir); (void) config_get(data, "MaximumHeaders", &conf->conf_maxhdrsz, sizeof conf->conf_maxhdrsz); (void) config_get(data, "MaximumSignaturesToVerify", &conf->conf_maxverify, sizeof conf->conf_maxverify); #ifdef _FFR_IDENTITY_HEADER (void) config_get(data, "IdentityHeader", &conf->conf_identityhdr, sizeof conf->conf_identityhdr); (void) config_get(data, "IdentityHeaderRemove", &conf->conf_rmidentityhdr, sizeof conf->conf_rmidentityhdr); #endif /* _FFR_IDENTITY_HEADER */ if (conf->conf_siglimit == NULL) { (void) config_get(data, "Minimum", &conf->conf_siglimit, sizeof conf->conf_siglimit); } if (conf->conf_modestr == NULL) { (void) config_get(data, "Mode", &conf->conf_modestr, sizeof conf->conf_modestr); } if (!dkimf_parsehandler(data, "On-Default", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-BadSignature", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-DNSError", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-KeyNotFound", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-InternalError", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-NoSignature", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-PolicyError", &conf->conf_handling, err, errlen) || #ifdef _FFR_REPUTATION !dkimf_parsehandler(data, "On-ReptuationError", &conf->conf_handling, err, errlen) || #endif /* _FFR_REPUTATION */ !dkimf_parsehandler(data, "On-Security", &conf->conf_handling, err, errlen) || !dkimf_parsehandler(data, "On-SignatureError", &conf->conf_handling, err, errlen)) return -1; (void) config_get(data, "RemoveARAll", &conf->conf_remarall, sizeof conf->conf_remarall); (void) config_get(data, "KeepAuthResults", &conf->conf_keepar, sizeof conf->conf_keepar); (void) config_get(data, "RemoveOldSignatures", &conf->conf_remsigs, sizeof conf->conf_remsigs); if (!conf->conf_reqhdrs) { (void) config_get(data, "RequiredHeaders", &conf->conf_reqhdrs, sizeof conf->conf_reqhdrs); } if (conf->conf_selector == NULL) { (void) config_get(data, "Selector", &conf->conf_selector, sizeof conf->conf_selector); } #ifdef _FFR_SENDER_MACRO if (conf->conf_sendermacro == NULL) { (void) config_get(data, "SenderMacro", &conf->conf_sendermacro, sizeof conf->conf_sendermacro); } #endif /* _FFR_SENDER_MACRO */ if (!conf->conf_sendreports) { (void) config_get(data, "SendReports", &conf->conf_sendreports, sizeof conf->conf_sendreports); } (void) config_get(data, "MTACommand", &conf->conf_mtacommand, sizeof conf->conf_mtacommand); (void) config_get(data, "ReportAddress", &conf->conf_reportaddr, sizeof conf->conf_reportaddr); (void) config_get(data, "ReportBccAddress", &conf->conf_reportaddrbcc, sizeof conf->conf_reportaddrbcc); if (conf->conf_signalgstr == NULL) { (void) config_get(data, "SignatureAlgorithm", &conf->conf_signalgstr, sizeof conf->conf_signalgstr); } tmpint = 0; (void) config_get(data, "SignatureTTL", &tmpint, sizeof tmpint); if (tmpint != 0) conf->conf_sigttl = (unsigned long) tmpint; #ifdef _FFR_STATS (void) config_get(data, "Statistics", &conf->conf_statspath, sizeof conf->conf_statspath); (void) config_get(data, "StatisticsPrefix", &conf->conf_reportprefix, sizeof conf->conf_reportprefix); str = NULL; (void) config_get(data, "StatisticsName", &str, sizeof str); if (str != NULL) conf->conf_reporthost = str; #endif /* _FFR_STATS */ if (!conf->conf_subdomains) { (void) config_get(data, "SubDomains", &conf->conf_subdomains, sizeof conf->conf_subdomains); } if (!conf->conf_dolog) { (void) config_get(data, "Syslog", &conf->conf_dolog, sizeof conf->conf_dolog); } if (!conf->conf_logwhy) { (void) config_get(data, "LogWhy", &conf->conf_logwhy, sizeof conf->conf_logwhy); } (void) config_get(data, "LogResults", &conf->conf_logresults, sizeof conf->conf_logresults); (void) config_get(data, "MultipleSignatures", &conf->conf_multisig, sizeof conf->conf_multisig); (void) config_get(data, "SyslogSuccess", &conf->conf_dolog_success, sizeof conf->conf_dolog_success); (void) config_get(data, "WeakSyntaxChecks", &conf->conf_weaksyntax, sizeof conf->conf_weaksyntax); #ifdef _FFR_LUA_ONLY_SIGNING (void) config_get(data, "LuaOnlySigning", &conf->conf_luasigning, sizeof conf->conf_luasigning); #endif /* _FFR_LUA_ONLY_SIGNING */ (void) config_get(data, "IgnoreMalformedMail", &conf->conf_passmalformed, sizeof conf->conf_passmalformed); (void) config_get(data, "DisableCryptoInit", &conf->conf_disablecryptoinit, sizeof conf->conf_disablecryptoinit); if (!conf->conf_addswhdr) { (void) config_get(data, "X-Header", &conf->conf_addswhdr, sizeof conf->conf_addswhdr); if (conf->conf_addswhdr) { if (conf->conf_dolog) { syslog(LOG_WARNING, "\"X-Header\" deprecated; use \"SoftwareHeader\" instead"); } } else { (void) config_get(data, "SoftwareHeader", &conf->conf_addswhdr, sizeof conf->conf_addswhdr); } } (void) config_get(data, "DomainKeysCompat", &conf->conf_acceptdk, sizeof conf->conf_acceptdk); (void) config_get(data, "CaptureUnknownErrors", &conf->conf_capture, sizeof conf->conf_capture); #ifndef SMFIF_QUARANTINE if (conf->conf_capture) { strlcpy(err, "quarantining not supported (required for CaptureUnknownErrors", errlen); return -1; } #endif /* SMFIF_QUARANTINE */ (void) config_get(data, "AllowSHA1Only", &conf->conf_allowsha1only, sizeof conf->conf_allowsha1only); #ifdef USE_LDAP btmp = FALSE; (void) config_get(data, "LDAPDisableCache", &btmp, sizeof btmp); if (btmp) dkimf_db_flags(DKIMF_DB_FLAG_NOCACHE); else dkimf_db_flags(0); (void) config_get(data, "LDAPUseTLS", &conf->conf_ldap_usetls, sizeof conf->conf_ldap_usetls); if (conf->conf_ldap_usetls) dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "y"); else dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_USETLS, "n"); (void) config_get(data, "LDAPTimeout", &conf->conf_ldap_timeout, sizeof conf->conf_ldap_timeout); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_TIMEOUT, conf->conf_ldap_timeout); (void) config_get(data, "LDAPKeepaliveIdle", &conf->conf_ldap_kaidle, sizeof conf->conf_ldap_kaidle); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_KA_IDLE, conf->conf_ldap_kaidle); (void) config_get(data, "LDAPKeepaliveProbes", &conf->conf_ldap_kaprobes, sizeof conf->conf_ldap_kaprobes); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_KA_PROBES, conf->conf_ldap_kaprobes); (void) config_get(data, "LDAPKeepaliveInterval", &conf->conf_ldap_kainterval, sizeof conf->conf_ldap_kainterval); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_KA_INTERVAL, conf->conf_ldap_kainterval); (void) config_get(data, "LDAPAuthMechanism", &conf->conf_ldap_authmech, sizeof conf->conf_ldap_authmech); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHMECH, conf->conf_ldap_authmech); # ifdef USE_SASL (void) config_get(data, "LDAPAuthName", &conf->conf_ldap_authname, sizeof conf->conf_ldap_authname); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHNAME, conf->conf_ldap_authname); (void) config_get(data, "LDAPAuthRealm", &conf->conf_ldap_authrealm, sizeof conf->conf_ldap_authrealm); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHREALM, conf->conf_ldap_authrealm); (void) config_get(data, "LDAPAuthUser", &conf->conf_ldap_authuser, sizeof conf->conf_ldap_authuser); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_AUTHUSER, conf->conf_ldap_authuser); # endif /* USE_SASL */ (void) config_get(data, "LDAPBindPassword", &conf->conf_ldap_bindpw, sizeof conf->conf_ldap_bindpw); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDPW, conf->conf_ldap_bindpw); (void) config_get(data, "LDAPBindUser", &conf->conf_ldap_binduser, sizeof conf->conf_ldap_binduser); dkimf_db_set_ldap_param(DKIMF_LDAP_PARAM_BINDUSER, conf->conf_ldap_binduser); #endif /* USE_LDAP */ (void) config_get(data, "Nameservers", &conf->conf_nslist, sizeof conf->conf_nslist); (void) config_get(data, "TrustAnchorFile", &conf->conf_trustanchorpath, sizeof conf->conf_trustanchorpath); if (conf->conf_trustanchorpath != NULL && access(conf->conf_trustanchorpath, R_OK) != 0) { snprintf(err, errlen, "%s: %s", conf->conf_trustanchorpath, strerror(errno)); return -1; } (void) config_get(data, "ResolverConfiguration", &conf->conf_resolverconfig, sizeof conf->conf_resolverconfig); str = NULL; (void) config_get(data, "BogusKey", &str, sizeof str); if (str != NULL) { int c; c = dkimf_lookup_strtoint(str, dkimf_keyactions); if (c == -1) { snprintf(err, errlen, "unknown key action '%s'", str); return -1; } conf->conf_boguskey = c; } else { conf->conf_boguskey = DKIMF_KEYACTIONS_FAIL; } str = NULL; (void) config_get(data, "UnprotectedKey", &str, sizeof str); if (str != NULL) { int c; c = dkimf_lookup_strtoint(str, dkimf_keyactions); if (c == -1) { snprintf(err, errlen, "unknown key action '%s'", str); return -1; } conf->conf_unprotectedkey = c; } else { conf->conf_unprotectedkey = DKIMF_KEYACTIONS_NONE; } #ifdef USE_LUA str = NULL; (void) config_get(data, "SetupPolicyScript", &str, sizeof str); if (str != NULL) { int fd; ssize_t rlen; struct stat s; struct dkimf_lua_script_result lres; fd = open(str, O_RDONLY, 0); if (fd < 0) { snprintf(err, errlen, "%s: open(): %s", str, strerror(errno)); return -1; } if (fstat(fd, &s) == -1) { snprintf(err, errlen, "%s: fstat(): %s", str, strerror(errno)); close(fd); return -1; } conf->conf_setupscript = malloc(s.st_size + 1); if (conf->conf_setupscript == NULL) { snprintf(err, errlen, "malloc(): %s", strerror(errno)); close(fd); return -1; } memset(conf->conf_setupscript, '\0', s.st_size + 1); rlen = read(fd, conf->conf_setupscript, s.st_size); if (rlen == -1) { snprintf(err, errlen, "%s: read(): %s", str, strerror(errno)); close(fd); return -1; } else if (rlen < s.st_size) { snprintf(err, errlen, "%s: early EOF", str); close(fd); return -1; } close(fd); memset(&lres, '\0', sizeof lres); if (dkimf_lua_setup_hook(NULL, conf->conf_setupscript, 0, str, &lres, &conf->conf_setupfunc, &conf->conf_setupfuncsz) != 0) { strlcpy(err, lres.lrs_error, errlen); free(lres.lrs_error); return -1; } } str = NULL; (void) config_get(data, "ScreenPolicyScript", &str, sizeof str); if (str != NULL) { int fd; ssize_t rlen; struct stat s; struct dkimf_lua_script_result lres; fd = open(str, O_RDONLY, 0); if (fd < 0) { snprintf(err, errlen, "%s: open(): %s", str, strerror(errno)); return -1; } if (fstat(fd, &s) == -1) { snprintf(err, errlen, "%s: fstat(): %s", str, strerror(errno)); close(fd); return -1; } conf->conf_screenscript = malloc(s.st_size + 1); if (conf->conf_screenscript == NULL) { snprintf(err, errlen, "malloc(): %s", strerror(errno)); close(fd); return -1; } memset(conf->conf_screenscript, '\0', s.st_size + 1); rlen = read(fd, conf->conf_screenscript, s.st_size); if (rlen == -1) { snprintf(err, errlen, "%s: read(): %s", str, strerror(errno)); close(fd); return -1; } else if (rlen < s.st_size) { snprintf(err, errlen, "%s: early EOF", str); close(fd); return -1; } close(fd); memset(&lres, '\0', sizeof lres); if (dkimf_lua_screen_hook(NULL, conf->conf_screenscript, 0, str, &lres, &conf->conf_screenfunc, &conf->conf_screenfuncsz) != 0) { strlcpy(err, lres.lrs_error, errlen); free(lres.lrs_error); return -1; } } # ifdef _FFR_STATSEXT str = NULL; (void) config_get(data, "StatisticsPolicyScript", &str, sizeof str); if (str != NULL) { int fd; ssize_t rlen; struct stat s; struct dkimf_lua_script_result lres; fd = open(str, O_RDONLY, 0); if (fd < 0) { snprintf(err, errlen, "%s: open(): %s", str, strerror(errno)); return -1; } if (fstat(fd, &s) == -1) { snprintf(err, errlen, "%s: fstat(): %s", str, strerror(errno)); close(fd); return -1; } conf->conf_statsscript = malloc(s.st_size + 1); if (conf->conf_statsscript == NULL) { snprintf(err, errlen, "malloc(): %s", strerror(errno)); close(fd); return -1; } memset(conf->conf_statsscript, '\0', s.st_size + 1); rlen = read(fd, conf->conf_statsscript, s.st_size); if (rlen == -1) { snprintf(err, errlen, "%s: read(): %s", str, strerror(errno)); close(fd); return -1; } else if (rlen < s.st_size) { snprintf(err, errlen, "%s: early EOF", str); close(fd); return -1; } close(fd); memset(&lres, '\0', sizeof lres); if (dkimf_lua_stats_hook(NULL, conf->conf_statsscript, 0, str, &lres, &conf->conf_statsfunc, &conf->conf_statsfuncsz) != 0) { strlcpy(err, lres.lrs_error, errlen); free(lres.lrs_error); return -1; } } # endif /* _FFR_STATSEXT */ str = NULL; (void) config_get(data, "FinalPolicyScript", &str, sizeof str); if (str != NULL) { int fd; ssize_t rlen; struct stat s; struct dkimf_lua_script_result lres; fd = open(str, O_RDONLY, 0); if (fd < 0) { snprintf(err, errlen, "%s: open(): %s", str, strerror(errno)); return -1; } if (fstat(fd, &s) == -1) { snprintf(err, errlen, "%s: fstat(): %s", str, strerror(errno)); close(fd); return -1; } conf->conf_finalscript = malloc(s.st_size + 1); if (conf->conf_finalscript == NULL) { snprintf(err, errlen, "malloc(): %s", strerror(errno)); close(fd); return -1; } memset(conf->conf_finalscript, '\0', s.st_size + 1); rlen = read(fd, conf->conf_finalscript, s.st_size); if (rlen == -1) { snprintf(err, errlen, "%s: read(): %s", str, strerror(errno)); close(fd); return -1; } else if (rlen < s.st_size) { snprintf(err, errlen, "%s: early EOF", str); close(fd); return -1; } close(fd); memset(&lres, '\0', sizeof lres); if (dkimf_lua_final_hook(NULL, conf->conf_finalscript, 0, str, &lres, &conf->conf_finalfunc, &conf->conf_finalfuncsz) != 0) { strlcpy(err, lres.lrs_error, errlen); free(lres.lrs_error); return -1; } } #endif /* USE_LUA */ if (become == NULL) { (void) config_get(data, "Userid", &become, sizeof become); } } #if defined(USE_LDAP) || defined(USE_ODBX) if (conf->conf_softstart) dbflags |= DKIMF_DB_FLAG_SOFTSTART; #endif /* defined(USE_LDAP) || defined(USE_ODBX) */ if (basedir[0] != '\0') { if (chdir(basedir) != 0) { snprintf(err, errlen, "%s: chdir(): %s", basedir, strerror(errno)); return -1; } } str = NULL; if (conf->conf_peerfile != NULL) { str = conf->conf_peerfile; } else if (data != NULL) { (void) config_get(data, "PeerList", &str, sizeof str); } if (str != NULL && !testmode) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_peerdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } if (conf->conf_testdnsdata != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_testdnsdb, conf->conf_testdnsdata, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } /* internal list */ str = NULL; if (conf->conf_internalfile != NULL) { str = conf->conf_internalfile; } else if (data != NULL) { (void) config_get(data, "InternalHosts", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_internal, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } else { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_internal, DEFINTERNAL, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", DEFINTERNAL, dberr); return -1; } } /* external ignore list */ str = NULL; if (conf->conf_externalfile != NULL) { str = conf->conf_externalfile; } else if (data != NULL) { (void) config_get(data, "ExternalIgnoreList", &str, sizeof str); } if (str != NULL && !testmode) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_exignore, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } /* exempt domains list */ str = NULL; if (conf->conf_exemptfile != NULL) { str = conf->conf_exemptfile; } else if (data != NULL) { (void) config_get(data, "ExemptDomains", &str, sizeof str); } if (str != NULL && !testmode) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_exemptdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } /* BodyLengthDB */ str = NULL; if (data != NULL) (void) config_get(data, "BodyLengthDB", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_bldb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) (void) config_get(data, "SignHeaders", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_signhdrsdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) (void) config_get(data, "RemoveARFrom", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_remardb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } #ifdef _FFR_ATPS str = NULL; if (data != NULL) { (void) config_get(data, "ATPSHashAlgorithm", &conf->conf_atpshash, sizeof conf->conf_atpshash); (void) config_get(data, "ATPSDomains", &str, sizeof str); } if (dkimf_lookup_strtoint(conf->conf_atpshash, dkimf_atpshash) != 1) { snprintf(err, errlen, "unknown ATPS hash \"%s\"", conf->conf_atpshash); return -1; } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_atpsdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } #endif /* _FFR_ATPS */ str = NULL; if (data != NULL) (void) config_get(data, "DontSignMailTo", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_dontsigntodb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) (void) config_get(data, "MustBeSigned", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_mbsdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (conf->conf_omitlist != NULL) { str = conf->conf_omitlist; } else if (data != NULL) { (void) config_get(data, "OmitHeaders", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_omithdrdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) { (void) config_get(data, "MTA", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_mtasdb, str, (dbflags | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } status = dkimf_db_mkarray(conf->conf_mtasdb, &conf->conf_mtas, NULL); if (status == -1) return -1; } str = NULL; if (data != NULL) (void) config_get(data, "OverSignHeaders", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_oversigndb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) (void) config_get(data, "SenderHeaders", &str, sizeof str); if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_senderhdrsdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } status = dkimf_db_mkarray(conf->conf_senderhdrsdb, &conf->conf_senderhdrs, NULL); if (status == -1) return -1; } #ifdef _FFR_VBR if (data != NULL) { (void) config_get(data, "VBR-Type", &conf->conf_vbr_deftype, sizeof conf->conf_vbr_deftype); (void) config_get(data, "VBR-Certifiers", &conf->conf_vbr_defcert, sizeof conf->conf_vbr_defcert); } str = NULL; if (data != NULL) { (void) config_get(data, "VBR-TrustedCertifiers", &str, sizeof str); } if (str != NULL) { char *dberr = NULL; int status; status = dkimf_db_open(&conf->conf_vbr_trusteddb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } (void) dkimf_db_mkarray(conf->conf_vbr_trusteddb, (char ***) &conf->conf_vbr_trusted, NULL); } if (data != NULL) { (void) config_get(data, "VBR-PurgeFields", &conf->conf_vbr_purge, sizeof conf->conf_vbr_purge); (void) config_get(data, "VBR-TrustedCertifiersOnly", &conf->conf_vbr_trustedonly, sizeof conf->conf_vbr_trustedonly); } #endif /* _FFR_VBR */ if (data != NULL) { (void) config_get(data, "SigningTable", &conf->conf_signtable, sizeof conf->conf_signtable); if (conf->conf_signtable != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_signtabledb, conf->conf_signtable, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_ASCIIONLY | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", conf->conf_signtable, dberr); return -1; } } } if (data != NULL) { (void) config_get(data, "KeyTable", &conf->conf_keytable, sizeof conf->conf_keytable); if (conf->conf_keytable == NULL) { (void) config_get(data, "KeyFile", &conf->conf_keyfile, sizeof conf->conf_keyfile); } else { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_keytabledb, conf->conf_keytable, (dbflags | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", conf->conf_keytable, dberr); return -1; } conf->conf_selector = NULL; } } if (conf->conf_signtabledb != NULL && conf->conf_keytabledb == NULL) { snprintf(err, errlen, "use of SigningTable requires KeyTable"); return -1; } str = NULL; if (data != NULL) { (void) config_get(data, "TrustSignaturesFrom", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_thirdpartydb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } #ifdef _FFR_RESIGN str = NULL; if (conf->conf_resign != NULL) { str = conf->conf_resign; } else if (data != NULL) { (void) config_get(data, "ResignMailTo", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_resigndb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } #endif /* _FFR_RESIGN */ #ifdef _FFR_CONDITIONAL str = NULL; if (conf->conf_conditional != NULL) { str = conf->conf_conditional; } else if (data != NULL) { (void) config_get(data, "ConditionalSignatures", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_conditionaldb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_RATE_LIMIT str = NULL; if (data != NULL) { (void) config_get(data, "RateLimits", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_ratelimitdb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) { (void) config_get(data, "FlowData", &str, sizeof str); (void) config_get(data, "FlowDataTTL", &conf->conf_flowdatattl, sizeof conf->conf_flowdatattl); (void) config_get(data, "FlowDataFactor", &conf->conf_flowfactor, sizeof conf->conf_flowfactor); } if (str != NULL) { int dbtype; int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_flowdatadb, str, (dbflags | DKIMF_DB_FLAG_ICASE | DKIMF_DB_FLAG_MAKELOCK), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } dbtype = dkimf_db_type(conf->conf_flowdatadb); if (dbtype != DKIMF_DB_TYPE_BDB) { snprintf(err, errlen, "%s: invalid data set type for FlowData", str); return -1; } } #endif /* _FFR_RATE_LIMIT */ str = NULL; if (conf->conf_domlist != NULL) { str = conf->conf_domlist; } else if (data != NULL) { (void) config_get(data, "Domain", &str, sizeof str); } if (str != NULL && conf->conf_keytabledb == NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_domainsdb, str, (dbflags | DKIMF_DB_FLAG_READONLY | DKIMF_DB_FLAG_ICASE), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) { (void) config_get(data, "MacroList", &str, sizeof str); } if (str != NULL) { int status; int dbtype; char *dberr = NULL; status = dkimf_db_open(&conf->conf_macrosdb, str, (dbflags | DKIMF_DB_FLAG_READONLY | DKIMF_DB_FLAG_VALLIST | DKIMF_DB_FLAG_MATCHBOTH), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } dbtype = dkimf_db_type(conf->conf_macrosdb); if (dbtype != DKIMF_DB_TYPE_FILE && dbtype != DKIMF_DB_TYPE_CSL) { snprintf(err, errlen, "%s: invalid data set type for MacroList", str); return -1; } (void) dkimf_db_mkarray(conf->conf_macrosdb, &conf->conf_macros, NULL); } if (conf->conf_signalgstr != NULL) { conf->conf_signalg = dkimf_lookup_strtoint(conf->conf_signalgstr, dkimf_sign); if (conf->conf_signalg == -1) { snprintf(err, errlen, "unknown signing algorithm \"%s\"", conf->conf_signalgstr); return -1; } } else { conf->conf_signalg = DKIM_SIGN_DEFAULT; } if (conf->conf_canonstr != NULL) { char *p; p = strchr(conf->conf_canonstr, '/'); if (p == NULL) { conf->conf_hdrcanon = dkimf_lookup_strtoint(conf->conf_canonstr, dkimf_canon); if (conf->conf_hdrcanon == -1) { snprintf(err, errlen, "unknown canonicalization algorithm \"%s\"", conf->conf_canonstr); return -1; } conf->conf_bodycanon = DKIM_CANON_DEFAULT; } else { *p = '\0'; conf->conf_hdrcanon = dkimf_lookup_strtoint(conf->conf_canonstr, dkimf_canon); if (conf->conf_hdrcanon == -1) { snprintf(err, errlen, "unknown canonicalization algorithm \"%s\"", conf->conf_canonstr); return -1; } conf->conf_bodycanon = dkimf_lookup_strtoint(p + 1, dkimf_canon); if (conf->conf_bodycanon == -1) { snprintf(err, errlen, "unknown canonicalization algorithm \"%s\"", p + 1); return -1; } *p = '/'; } } str = NULL; if (conf->conf_siglimit != NULL) { str = conf->conf_siglimit; } else if (data != NULL) { (void) config_get(data, "Minimum", &str, sizeof str); } if (str != NULL) { unsigned long tmpl; char *p; errno = 0; if (str[0] == '-') { tmpl = ULONG_MAX; errno = ERANGE; } tmpl = strtoul(str, &p, 10); if (tmpl > UINT_MAX || errno != 0) { snprintf(err, errlen, "illegal value for \"Minimum\""); return -1; } conf->conf_sigmin = (unsigned int) tmpl; if (*p == '%') { if (conf->conf_sigmin > 100) { snprintf(err, errlen, "illegal value for \"Minimum\""); return -1; } conf->conf_sigmintype = SIGMIN_PERCENT; } else if (*p == '+') { conf->conf_sigmintype = SIGMIN_MAXADD; } else if (*p != '\0') { snprintf(err, errlen, "illegal value for \"Minimum\""); return -1; } } maxsign = -1; if (data != NULL) { (void) config_get(data, "MaximumSignedBytes", &maxsign, sizeof maxsign); } if (maxsign != -1) { conf->conf_signbytes = (long) maxsign; conf->conf_blen = TRUE; } if (conf->conf_modestr == NULL) { conf->conf_mode = (testmode ? DKIMF_MODE_VERIFIER : DKIMF_MODE_DEFAULT); } else { char *p; conf->conf_mode = 0; for (p = conf->conf_modestr; *p != '\0'; p++) { switch (*p) { case 's': conf->conf_mode |= DKIMF_MODE_SIGNER; break; case 'v': conf->conf_mode |= DKIMF_MODE_VERIFIER; break; default: snprintf(err, errlen, "unknown mode \"%c\"", *p); return -1; } } } #ifdef _FFR_REPLACE_RULES /* replacement list */ str = NULL; if (data != NULL) { (void) config_get(data, "ReplaceHeaders", &str, sizeof str); } if (str != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_rephdrsdb, str, (dbflags | DKIMF_DB_FLAG_READONLY | DKIMF_DB_FLAG_ICASE), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", str, dberr); return -1; } } str = NULL; if (data != NULL) (void) config_get(data, "ReplaceRules", &str, sizeof str); if (str != NULL) { FILE *f; f = fopen(str, "r"); if (f == NULL) { snprintf(err, errlen, "%s: fopen(): %s", str, strerror(errno)); return -1; } if (!dkimf_load_replist(f, &conf->conf_replist)) { snprintf(err, errlen, "failed to load ReplaceRules from %s", str); fclose(f); return -1; } fclose(f); } #endif /* _FFR_REPLACE_RULES */ #ifdef _FFR_REPUTATION if (data != NULL) { (void) config_get(data, "ReputationTest", &conf->conf_reptest, sizeof conf->conf_reptest); (void) config_get(data, "ReputationVerbose", &conf->conf_repverbose, sizeof conf->conf_repverbose); (void) config_get(data, "ReputationLimits", &conf->conf_replimits, sizeof conf->conf_replimits); (void) config_get(data, "ReputationLimitModifiers", &conf->conf_replimitmods, sizeof conf->conf_replimitmods); (void) config_get(data, "ReputationCache", &conf->conf_repcache, sizeof conf->conf_repcache); (void) config_get(data, "ReputationCacheTTL", &conf->conf_repcachettl, sizeof conf->conf_repcachettl); (void) config_get(data, "ReputationDuplicates", &conf->conf_repdups, sizeof conf->conf_repdups); (void) config_get(data, "ReputationRatios", &conf->conf_repratios, sizeof conf->conf_repratios); (void) config_get(data, "ReputationLowTime", &conf->conf_replowtime, sizeof conf->conf_replowtime); (void) config_get(data, "ReputationTimeFactor", &conf->conf_repfactor, sizeof conf->conf_repfactor); (void) config_get(data, "ReputationTimeout", &conf->conf_reptimeout, sizeof conf->conf_reptimeout); (void) config_get(data, "ReputationSpamCheck", &conf->conf_repspamcheck, sizeof conf->conf_repspamcheck); (void) config_get(data, "ReputationMinimum", &conf->conf_repminimum, sizeof conf->conf_repminimum); } if (conf->conf_repspamcheck != NULL) { size_t tmplen; char tmpre[BUFRSZ + 1]; tmplen = strlen(conf->conf_repspamcheck); if (tmplen < 3 || conf->conf_repspamcheck[0] != '/' || conf->conf_repspamcheck[tmplen - 1] != '/') { snprintf(err, errlen, "invalid value for ReputationSpamCheck"); return -1; } strlcpy(tmpre, conf->conf_repspamcheck + 1, sizeof tmpre); tmpre[tmplen - 2] = '\0'; if (regcomp(&conf->conf_repspamre, tmpre, REG_EXTENDED) != 0) { snprintf(err, errlen, "unusable value for ReputationSpamCheck"); return -1; } } if (conf->conf_replowtime != NULL) { int status; char *dberr = NULL; status = dkimf_db_open(&conf->conf_replowtimedb, conf->conf_replowtime, (dbflags | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", conf->conf_replowtime, dberr); return -1; } } if (conf->conf_repratios != NULL) { int status; char *dberr = NULL; if (conf->conf_replimits != NULL) { status = dkimf_db_open(&conf->conf_replimitsdb, conf->conf_replimits, (dbflags | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", conf->conf_replimits, dberr); return -1; } } if (conf->conf_replimitmods != NULL) { status = dkimf_db_open(&conf->conf_replimitmodsdb, conf->conf_replimitmods, (dbflags | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", conf->conf_replimitmods, dberr); return -1; } } status = dkimf_db_open(&conf->conf_repratiosdb, conf->conf_repratios, (dbflags | DKIMF_DB_FLAG_READONLY), NULL, &dberr); if (status != 0) { snprintf(err, errlen, "%s: dkimf_db_open(): %s", conf->conf_repratios, dberr); return -1; } if (dkimf_rep_init(&conf->conf_rep, conf->conf_repfactor, conf->conf_repminimum, conf->conf_repcachettl, conf->conf_repcache, conf->conf_repdups, conf->conf_replimitsdb, conf->conf_replimitmodsdb, conf->conf_repratiosdb, conf->conf_replowtimedb) != 0) { snprintf(err, errlen, "can't initialize reputation subsystem"); return -1; } } #endif /* _FFR_REPUTATION */ #ifdef _FFR_REPRRD if (data != NULL) { int hashdepth = REPRRD_DEFHASHDEPTH; char *root = NULL; (void) config_get(data, "ReputationTest", &conf->conf_reptest, sizeof conf->conf_reptest); (void) config_get(data, "ReputationVerbose", &conf->conf_repverbose, sizeof conf->conf_repverbose); (void) config_get(data, "ReputationRRDHashDepth", &hashdepth, sizeof hashdepth); (void) config_get(data, "ReputationRRDRoot", &root, sizeof root); if (hashdepth >= 0 && root != NULL) { conf->conf_reprrd = reprrd_init(root, hashdepth); if (conf->conf_reprrd == NULL) { snprintf(err, errlen, "can't initialize reputation subsystem"); return -1; } } } #endif /* _FFR_REPRRD */ dkimf_reportaddr(conf); /* load the secret key, if one was specified */ if (conf->conf_keyfile != NULL) { int status; int fd; ssize_t rlen; ino_t ino; uid_t asuser = (uid_t) -1; u_char *s33krit; struct stat s; fd = open(conf->conf_keyfile, O_RDONLY, 0); if (fd < 0) { if (conf->conf_dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "%s: open(): %s", conf->conf_keyfile, strerror(errno)); errno = saveerrno; } snprintf(err, errlen, "%s: open(): %s", conf->conf_keyfile, strerror(errno)); return -1; } status = fstat(fd, &s); if (status != 0) { if (conf->conf_dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "%s: stat(): %s", conf->conf_keyfile, strerror(errno)); errno = saveerrno; } snprintf(err, errlen, "%s: stat(): %s", conf->conf_keyfile, strerror(errno)); close(fd); return -1; } else if (!S_ISREG(s.st_mode)) { snprintf(err, errlen, "%s: open(): Not a regular file", conf->conf_keyfile); close(fd); return -1; } if (become != NULL) { struct passwd *pw; char *p; char tmp[BUFRSZ + 1]; strlcpy(tmp, become, sizeof tmp); p = strchr(tmp, ':'); if (p != NULL) *p = '\0'; pw = getpwnam(tmp); if (pw == NULL) { snprintf(err, errlen, "%s: no such user", tmp); close(fd); return -1; } asuser = pw->pw_uid; } if (!dkimf_securefile(conf->conf_keyfile, &ino, asuser, err, errlen) || (ino != (ino_t) -1 && ino != s.st_ino)) { if (conf->conf_dolog) { int sev; sev = (conf->conf_safekeys ? LOG_ERR : LOG_WARNING); syslog(sev, "%s: key data is not secure: %s", conf->conf_keyfile, err); } if (conf->conf_safekeys) return -1; } s33krit = malloc(s.st_size + 1); if (s33krit == NULL) { if (conf->conf_dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "malloc(): %s", strerror(errno)); errno = saveerrno; } snprintf(err, errlen, "malloc(): %s", strerror(errno)); return -1; } conf->conf_keylen = s.st_size + 1; rlen = read(fd, s33krit, s.st_size + 1); if (rlen == (ssize_t) -1) { if (conf->conf_dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "%s: read(): %s", conf->conf_keyfile, strerror(errno)); errno = saveerrno; } snprintf(err, errlen, "%s: read(): %s", conf->conf_keyfile, strerror(errno)); close(fd); free(s33krit); return -1; } else if (rlen != s.st_size) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: read() wrong size (%lu)", conf->conf_keyfile, (u_long) rlen); } snprintf(err, errlen, "%s: read() wrong size (%lu)", conf->conf_keyfile, (u_long) rlen); close(fd); free(s33krit); return -1; } close(fd); s33krit[s.st_size] = '\0'; conf->conf_seckey = s33krit; } /* confirm signing mode parameters */ if ((conf->conf_mode & DKIMF_MODE_SIGNER) != 0) { if ((conf->conf_selector != NULL && conf->conf_keyfile == NULL) || (conf->conf_selector == NULL && conf->conf_keyfile != NULL)) { snprintf(err, errlen, "KeyFile and Selector must both be defined or both be undefined"); return -1; } if (conf->conf_domainsdb != NULL && (conf->conf_selector == NULL || conf->conf_keyfile == NULL)) { snprintf(err, errlen, "Domain requires KeyFile and Selector"); return -1; } if (conf->conf_signtable != NULL && conf->conf_keytable == NULL) { snprintf(err, errlen, "SigningTable requires KeyTable"); return -1; } #ifdef USE_LUA if (conf->conf_keytable != NULL && conf->conf_signtable == NULL && conf->conf_setupscript == NULL) { snprintf(err, errlen, "KeyTable requires either SigningTable or SetupPolicyScript"); return -1; } #else /* USE_LUA */ if (conf->conf_keytable != NULL && conf->conf_signtable == NULL) { snprintf(err, errlen, "KeyTable requires SigningTable"); return -1; } #endif /* USE_LUA */ /* ** Verify that the SingingTable doesn't reference any ** missing KeyTable entries. */ if (conf->conf_signtabledb != NULL) { _Bool first = TRUE; _Bool found; struct dkimf_db_data dbd[3]; char keyname[BUFRSZ + 1]; char domain[BUFRSZ + 1]; char selector[BUFRSZ + 1]; char keydata[BUFRSZ + 1]; char signer[BUFRSZ + 1]; dbd[0].dbdata_flags = 0; memset(keyname, '\0', sizeof keyname); dbd[0].dbdata_buffer = keyname; dbd[0].dbdata_buflen = sizeof keyname - 1; dbd[0].dbdata_flags = 0; dbd[1].dbdata_buffer = signer; dbd[1].dbdata_buflen = sizeof signer - 1; dbd[1].dbdata_flags = 0; while (dkimf_db_walk(conf->conf_signtabledb, first, NULL, NULL, dbd, 2) == 0) { first = FALSE; found = FALSE; dbd[0].dbdata_buffer = domain; dbd[0].dbdata_buflen = sizeof domain - 1; dbd[0].dbdata_flags = 0; dbd[1].dbdata_buffer = selector; dbd[1].dbdata_buflen = sizeof selector - 1; dbd[1].dbdata_flags = 0; dbd[2].dbdata_buffer = keydata; dbd[2].dbdata_buflen = sizeof keydata - 1; dbd[2].dbdata_flags = DKIMF_DB_DATA_BINARY; if (dkimf_db_get(conf->conf_keytabledb, keyname, strlen(keyname), dbd, 3, &found) != 0 || !found || dbd[0].dbdata_buflen == 0 || dbd[1].dbdata_buflen == 0 || dbd[2].dbdata_buflen == 0) { snprintf(err, errlen, "could not find valid key record \"%s\" in KeyTable", keyname); return -1; } memset(keyname, '\0', sizeof keyname); dbd[0].dbdata_buffer = keyname; dbd[0].dbdata_buflen = sizeof keyname - 1; dbd[0].dbdata_flags = 0; } } } /* activate logging if requested */ if (conf->conf_dolog) { char *log_name = NULL; char *log_facility = NULL; if (data != NULL) { (void) config_get(data, "SyslogName", &log_name, sizeof log_name); (void) config_get(data, "SyslogFacility", &log_facility, sizeof log_facility); } dkimf_init_syslog(log_name, log_facility); } return 0; } /* ** DKIMF_DNS_INIT -- initialize and configure the DNS service in the ** DKIM library ** ** Parameters: ** lib -- DKIM library ** conf -- configuration handle ** err -- error string (returned) ** ** Return value: ** TRUE on success, FALSE otherwise */ static _Bool dkimf_dns_init(DKIM_LIB *lib, struct dkimf_config *conf, char **err) { int status; assert(lib != NULL); assert(conf != NULL); assert(err != NULL); status = dkim_dns_init(lib); if (status == DKIM_DNS_INVALID) { return TRUE; } else if (status == DKIM_DNS_ERROR) { if (err != NULL) *err = "failed to initialize resolver"; return FALSE; } if (conf->conf_nslist != NULL) { status = dkimf_dns_setnameservers(lib, conf->conf_nslist); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set nameserver list"; return FALSE; } } if (conf->conf_trustanchorpath != NULL) { if (access(conf->conf_trustanchorpath, R_OK) != 0) { if (err != NULL) *err = "can't access unbound trust anchor"; return FALSE; } status = dkimf_dns_trustanchor(lib, conf->conf_trustanchorpath); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to add trust anchor"; return FALSE; } } if (conf->conf_resolverconfig != NULL) { status = dkimf_dns_config(lib, conf->conf_resolverconfig); if (status != DKIM_DNS_SUCCESS) { if (err != NULL) *err = "failed to add resolver configuration file"; return FALSE; } } return TRUE; } /* ** DKIMF_CONFIG_SETLIB -- set library options based on configuration file ** ** Parameters: ** conf -- DKIM filter configuration data ** err -- error string (returned; may be NULL) ** ** Return value: ** TRUE on success, FALSE otherwise. */ static _Bool dkimf_config_setlib(struct dkimf_config *conf, char **err) { DKIM_STAT status; u_int opts; DKIM_LIB *lib; assert(conf != NULL); lib = conf->conf_libopendkim; if (lib == NULL) { lib = dkim_init(NULL, NULL); if (lib == NULL) { if (err != NULL) *err = "failed to initialize DKIM library"; return FALSE; } conf->conf_libopendkim = lib; } (void) dkim_options(lib, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &opts, sizeof opts); opts |= (DKIM_LIBFLAGS_ACCEPTV05 | DKIM_LIBFLAGS_DROPSIGNER); if (conf->conf_weaksyntax) opts |= DKIM_LIBFLAGS_BADSIGHANDLES; #ifdef QUERY_CACHE if (querycache) { opts |= DKIM_LIBFLAGS_CACHE; (void) time(&cache_lastlog); } #endif /* QUERY_CACHE */ (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &opts, sizeof opts); /* set the DNS callback */ (void) dkim_set_dns_callback(lib, dkimf_sendprogress, CBINTERVAL); if (conf->conf_minkeybits != 0) { (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_MINKEYBITS, &conf->conf_minkeybits, sizeof conf->conf_minkeybits); } if (conf->conf_testdnsdb != NULL) { (void) dkimf_filedns_setup(lib, conf->conf_testdnsdb); } else { #ifdef USE_UNBOUND (void) dkimf_unbound_setup(lib); #endif /* USE_UNBOUND */ if (!dkimf_dns_init(lib, conf, err)) return FALSE; else dkim_dns_close(lib); } (void) dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_TIMEOUT, &conf->conf_dnstimeout, sizeof conf->conf_dnstimeout); if (conf->conf_clockdrift != 0) { uint64_t drift = conf->conf_clockdrift; status = dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_CLOCKDRIFT, &drift, sizeof drift); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM clock drift limit"; return FALSE; } } if (conf->conf_sigttl != 0) { uint64_t sigtime = conf->conf_sigttl; status = dkim_options(lib, DKIM_OP_SETOPT, DKIM_OPTS_SIGNATURETTL, &sigtime, sizeof sigtime); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM signature TTL"; return FALSE; } } if (conf->conf_sendreports || conf->conf_keeptmpfiles || conf->conf_stricthdrs || conf->conf_blen || conf->conf_ztags || conf->conf_fixcrlf) { u_int opts; status = dkim_options(conf->conf_libopendkim, DKIM_OP_GETOPT, DKIM_OPTS_FLAGS, &opts, sizeof opts); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to retrieve DKIM library options"; return FALSE; } if (conf->conf_sendreports || conf->conf_keeptmpfiles) opts |= DKIM_LIBFLAGS_TMPFILES; if (conf->conf_keeptmpfiles) opts |= DKIM_LIBFLAGS_KEEPFILES; if (conf->conf_blen) opts |= DKIM_LIBFLAGS_SIGNLEN; if (conf->conf_ztags) opts |= DKIM_LIBFLAGS_ZTAGS; if (conf->conf_fixcrlf) opts |= DKIM_LIBFLAGS_FIXCRLF; if (conf->conf_acceptdk) opts |= DKIM_LIBFLAGS_ACCEPTDK; if (conf->conf_stricthdrs) opts |= DKIM_LIBFLAGS_STRICTHDRS; status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_FLAGS, &opts, sizeof opts); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } if (conf->conf_oversigndb != NULL) { status = dkimf_db_mkarray(conf->conf_oversigndb, &conf->conf_oversignhdrs, NULL); if (status == -1) { if (err != NULL) *err = "failed to generate DB array"; return FALSE; } status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_OVERSIGNHDRS, conf->conf_oversignhdrs, sizeof conf->conf_oversignhdrs); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } if (conf->conf_mbsdb != NULL) { status = dkimf_db_mkarray(conf->conf_mbsdb, &conf->conf_mbs, NULL); if (status == -1) { if (err != NULL) *err = "failed to generate DB array"; return FALSE; } status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_MUSTBESIGNED, conf->conf_mbs, sizeof conf->conf_mbs); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } if (conf->conf_omithdrdb != NULL) { status = dkimf_db_mkarray(conf->conf_omithdrdb, &conf->conf_omithdrs, (const char **) dkim_should_not_signhdrs); if (status == -1) { if (err != NULL) *err = "failed to generate DB array"; return FALSE; } status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_SKIPHDRS, conf->conf_omithdrs, sizeof conf->conf_omithdrs); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } else { status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_SKIPHDRS, (void *) dkim_should_not_signhdrs, sizeof (u_char **)); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } if (conf->conf_signhdrsdb != NULL) { status = dkimf_db_mkarray(conf->conf_signhdrsdb, &conf->conf_signhdrs, (const char **) dkim_should_signhdrs); if (status == -1) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, conf->conf_signhdrs, sizeof conf->conf_signhdrs); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } else { status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_SIGNHDRS, (void *) dkim_should_signhdrs, sizeof (u_char **)); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } } status = dkim_options(conf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_TMPDIR, (void *) conf->conf_tmpdir, sizeof conf->conf_tmpdir); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM library options"; return FALSE; } status = dkim_set_prescreen(conf->conf_libopendkim, dkimf_prescreen); if (status != DKIM_STAT_OK) { if (err != NULL) *err = "failed to set DKIM prescreen function"; return FALSE; } return TRUE; } /* ** DKIMF_CONFIG_RELOAD -- reload configuration if requested ** ** Parameters: ** None. ** ** Return value: ** None. ** ** Side effects: ** If a reload was requested and is successful, "curconf" now points ** to a new configuration handle. */ static void dkimf_config_reload(void) { struct dkimf_config *new; char errbuf[BUFRSZ + 1]; pthread_mutex_lock(&conf_lock); if (!reload) { pthread_mutex_unlock(&conf_lock); return; } if (conffile == NULL) { if (curconf->conf_dolog) syslog(LOG_ERR, "ignoring reload signal"); reload = FALSE; pthread_mutex_unlock(&conf_lock); return; } new = dkimf_config_new(); if (new == NULL) { if (curconf->conf_dolog) syslog(LOG_ERR, "malloc(): %s", strerror(errno)); } else { _Bool err = FALSE; u_int line; struct config *cfg; char *missing; char *errstr = NULL; char *deprecated = NULL; char path[MAXPATHLEN + 1]; strlcpy(path, conffile, sizeof path); cfg = config_load(conffile, dkimf_config, &line, path, sizeof path, &deprecated); if (cfg == NULL) { if (curconf->conf_dolog) { syslog(LOG_ERR, "%s: configuration error at line %u: %s", path, line, config_error()); } dkimf_config_free(new); err = TRUE; } if (deprecated != NULL) { char *action = "aborting"; if (allowdeprecated) action = "continuing"; if (curconf->conf_dolog) { syslog(LOG_WARNING, "%s: settings found for deprecated value(s): %s; %s", path, deprecated, action); } if (!allowdeprecated) { dkimf_config_free(new); err = TRUE; } } if (!err) { missing = config_check(cfg, dkimf_config); if (missing != NULL) { if (curconf->conf_dolog) { syslog(LOG_ERR, "%s: required parameter \"%s\" missing", conffile, missing); } config_free(cfg); dkimf_config_free(new); err = TRUE; } } if (!err && dkimf_config_load(cfg, new, errbuf, sizeof errbuf, NULL) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "%s: %s", conffile, errbuf); config_free(cfg); dkimf_config_free(new); err = TRUE; } if (!err && !dkimf_config_setlib(new, &errstr)) { if (curconf->conf_dolog) { syslog(LOG_WARNING, "can't configure DKIM library: %s; continuing", errstr); } config_free(cfg); dkimf_config_free(new); err = TRUE; } if (!err) { if (curconf->conf_refcnt == 0) dkimf_config_free(curconf); dolog = new->conf_dolog; curconf = new; new->conf_data = cfg; if (new->conf_dolog) { syslog(LOG_INFO, "configuration reloaded from %s", conffile); } } } reload = FALSE; pthread_mutex_unlock(&conf_lock); return; } /* ** DKIMF_CHECKBLDB -- determine if an envelope recipient is one for which ** signing should be done with body length tags ** ** Parameters: ** db -- DB handle ** to -- the recipient header ** jobid -- string of job ID for logging ** ** Return value: ** TRUE iff the recipient email was found in the body length database. */ static _Bool dkimf_checkbldb(DKIMF_DB db, char *to, char *jobid) { int c; _Bool exists = FALSE; DKIM_STAT status; char *domain; char *user; char *p; char addr[MAXADDRESS + 1]; char dbaddr[MAXADDRESS + 1]; strlcpy(addr, to, sizeof addr); status = dkim_mail_parse(addr, (u_char **) &user, (u_char **) &domain); if (status != 0 || user == NULL || domain == NULL) { if (dolog) { syslog(LOG_INFO, "%s: can't parse %s: header", jobid, to); } return FALSE; } for (p = domain; ; p = strchr(p + 1, '.')) { for (c = 0; c < 2; c++) { if (c == 1 && p == NULL) { dbaddr[0] = '*'; dbaddr[1] = '\0'; } else if (snprintf(dbaddr, sizeof dbaddr, "%s@%s", c == 0 ? user : "*", p == NULL ? "*" : p) >= (int) sizeof dbaddr) { if (dolog) { syslog(LOG_ERR, "%s: overflow parsing \"%s\"", jobid, to); } return FALSE; } status = dkimf_db_get(db, dbaddr, 0, NULL, 0, &exists); if (status == 0) { if (exists) return TRUE; } else if (dolog) { dkimf_db_error(db, dbaddr); } } if (p == NULL) break; } return FALSE; } /* ** DKIMF_STDIO -- set up the base descriptors to go nowhere ** ** Parameters: ** None. ** ** Return value: ** None. */ static void dkimf_stdio(void) { int devnull; /* this only fails silently, but that's OK */ devnull = open(_PATH_DEVNULL, O_RDWR, 0); if (devnull != -1) { (void) dup2(devnull, 0); (void) dup2(devnull, 1); (void) dup2(devnull, 2); if (devnull > 2) (void) close(devnull); } (void) setsid(); } /* ** DKIMF_SENDPROGRESS -- tell the MTA "we're working on it!" ** ** Parameters: ** ctx -- context ** ** Return value: ** None (yet). */ void dkimf_sendprogress(const void *ctx) { if (ctx != NULL) { struct connctx *cc; struct msgctx *dfc; cc = (struct connctx *) dkimf_getpriv((SMFICTX *) ctx); dfc = cc->cctx_msg; if (dfc->mctx_eom) { if (testmode) (void) dkimf_test_progress((SMFICTX *) ctx); #ifdef HAVE_SMFI_PROGRESS else (void) smfi_progress((SMFICTX *) ctx); #endif /* HAVE_SMFI_PROGRESS */ } } } /* ** DKIMF_INITCONTEXT -- initialize filter context ** ** Parameters: ** conf -- pointer to the configuration for this connection ** ** Return value: ** A pointer to an allocated and initialized filter context, or NULL ** on failure. ** ** Side effects: ** Crop circles near Birmingham. */ static msgctx dkimf_initcontext(struct dkimf_config *conf) { msgctx ctx; assert(conf != NULL); ctx = (msgctx) malloc(sizeof(struct msgctx)); if (ctx == NULL) return NULL; (void) memset(ctx, '\0', sizeof(struct msgctx)); ctx->mctx_status = DKIMF_STATUS_UNKNOWN; ctx->mctx_hdrcanon = conf->conf_hdrcanon; ctx->mctx_bodycanon = conf->conf_bodycanon; ctx->mctx_signalg = DKIM_SIGN_DEFAULT; ctx->mctx_queryalg = DKIM_QUERY_DEFAULT; #ifdef USE_UNBOUND ctx->mctx_dnssec_key = DKIM_DNSSEC_UNKNOWN; #endif /* USE_UNBOUND */ #ifdef _FFR_ATPS ctx->mctx_atps = DKIM_ATPS_UNKNOWN; #endif /* _FFR_ATPS */ #ifdef _FFR_REPUTATION # ifdef USE_GNUTLS (void) gnutls_hash_init(&ctx->mctx_hash, GNUTLS_DIG_SHA1); # else /* USE_GNUTLS */ SHA1_Init(&ctx->mctx_hash); # endif /* USE_GNUTLS */ #endif /* _FFR_REPUTATION */ return ctx; } /* ** DKIMF_LOG_SSL_ERRORS -- log any queued SSL library errors ** ** Parameters: ** dkim -- DKIM handle ** sig -- signature handle ** jobid -- job ID to include in log messages ** ** Return value: ** None. */ static void dkimf_log_ssl_errors(DKIM *dkim, DKIM_SIGINFO *sig, char *jobid) { char *selector; char *domain; char *algorithm; const char *errbuf; assert(dkim != NULL); assert(jobid != NULL); if (sig != NULL) { domain = dkim_sig_getdomain(sig); selector = dkim_sig_getselector(sig); algorithm = dkim_sig_getalgorithm(sig); errbuf = dkim_sig_getsslbuf(sig); } else { domain = NULL; selector = NULL; algorithm = NULL; errbuf = dkim_getsslbuf(dkim); } if (errbuf != NULL) { if (selector != NULL && domain != NULL && algorithm != NULL) { syslog(LOG_INFO, "%s: s=%s d=%s a=%s SSL %s", jobid, selector, domain, algorithm, errbuf); } else { syslog(LOG_INFO, "%s: SSL %s", jobid, errbuf); } } } /* ** DKIMF_CLEANUP -- release local resources related to a message ** ** Parameters: ** ctx -- milter context ** ** Return value: ** None. */ static void dkimf_cleanup(SMFICTX *ctx) { msgctx dfc; connctx cc; assert(ctx != NULL); cc = (connctx) dkimf_getpriv(ctx); if (cc == NULL) return; dfc = cc->cctx_msg; /* release memory, reset state */ if (dfc != NULL) { if (dfc->mctx_hqhead != NULL) { Header hdr; Header prev; hdr = dfc->mctx_hqhead; while (hdr != NULL) { TRYFREE(hdr->hdr_hdr); TRYFREE(hdr->hdr_val); prev = hdr; hdr = hdr->hdr_next; TRYFREE(prev); } } if (dfc->mctx_rcptlist != NULL) { struct addrlist *addr; struct addrlist *next; addr = dfc->mctx_rcptlist; while (addr != NULL) { next = addr->a_next; TRYFREE(addr->a_addr); TRYFREE(addr); addr = next; } } if (dfc->mctx_srhead != NULL) { struct signreq *sr; struct signreq *next; sr = dfc->mctx_srhead; while (sr != NULL) { next = sr->srq_next; if (sr->srq_dkim != NULL) dkim_free(sr->srq_dkim); TRYFREE(sr->srq_keydata); TRYFREE(sr->srq_domain); TRYFREE(sr->srq_selector); TRYFREE(sr->srq_signer); TRYFREE(sr); sr = next; } } if (dfc->mctx_dkimv != NULL) dkim_free(dfc->mctx_dkimv); #ifdef _FFR_VBR if (dfc->mctx_vbr != NULL) vbr_close(dfc->mctx_vbr); TRYFREE(dfc->mctx_vbrinfo); #endif /* _FFR_VBR */ if (dfc->mctx_tmpstr != NULL) dkimf_dstring_free(dfc->mctx_tmpstr); #ifdef _FFR_STATSEXT if (dfc->mctx_statsext != NULL) { struct statsext *cur; struct statsext *next; cur = dfc->mctx_statsext; while (cur != NULL) { next = cur->se_next; free(cur); cur = next; } } #endif /* _FFR_STATSEXT */ #ifdef USE_LUA if (dfc->mctx_luaglobalh != NULL) { struct lua_global *cur; struct lua_global *next; cur = dfc->mctx_luaglobalh; while (cur != NULL) { next = cur->lg_next; if (cur->lg_type == LUA_TNUMBER || cur->lg_type == LUA_TSTRING) free(cur->lg_value); free(cur); cur = next; } } #endif /* USE_LUA */ free(dfc); cc->cctx_msg = NULL; } } /* ** DKIMF_MILTERCODE -- apply an internal result code to libmilter ** ** Parameters: ** ctx -- milter context ** dmc -- DKIMF_MILTER_* code ** str -- quarantine string (optional) ** ** Return value: ** An SMFIS_* constant. */ sfsistat dkimf_miltercode(SMFICTX *ctx, int dmc, char *str) { assert(ctx != NULL); switch (dmc) { case DKIMF_MILTER_ACCEPT: return SMFIS_ACCEPT; case DKIMF_MILTER_DISCARD: return SMFIS_DISCARD; case DKIMF_MILTER_QUARANTINE: (void) dkimf_quarantine(ctx, str == NULL ? progname : str); return SMFIS_ACCEPT; case DKIMF_MILTER_REJECT: return SMFIS_REJECT; case DKIMF_MILTER_TEMPFAIL: return SMFIS_TEMPFAIL; } /* NOTREACHED */ return SMFIS_ACCEPT; } /* ** DKIMF_LIBSTATUS -- process a final status returned from libopendkim ** ** Parameters: ** ctx -- milter context ** dkim -- DKIM handle producing the status ** where -- what function reported the error ** status -- status returned by a libdk call (DKIM_STAT_*) ** ** Return value: ** An smfistat value to be returned to libmilter. */ static sfsistat dkimf_libstatus(SMFICTX *ctx, DKIM *dkim, char *where, int status) { int retcode = SMFIS_CONTINUE; msgctx dfc; connctx cc; DKIM_SIGINFO *sig; char *rcode = NULL; char *xcode = NULL; char *replytxt = NULL; struct dkimf_config *conf; u_char smtpprefix[BUFRSZ]; assert(ctx != NULL); cc = dkimf_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); conf = cc->cctx_config; memset(smtpprefix, '\0', sizeof smtpprefix); switch (status) { case DKIM_STAT_OK: retcode = SMFIS_CONTINUE; break; case DKIM_STAT_INTERNAL: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_internal, NULL); if (conf->conf_capture) dfc->mctx_capture = TRUE; if (conf->conf_dolog) { const char *err = NULL; const char *sslerr = NULL; if (dkim != NULL) err = dkim_geterror(dkim); if (err == NULL) err = strerror(errno); sslerr = dkim_getsslbuf(dkim); syslog(LOG_ERR, "%s: %s%sinternal error from libopendkim: %s%s%s", JOBID(dfc->mctx_jobid), where == NULL ? "" : where, where == NULL ? "" : ": ", err, sslerr == NULL ? "" : " ", sslerr == NULL ? "" : sslerr); } replytxt = "internal DKIM error"; break; case DKIM_STAT_BADSIG: assert(dkim != NULL); retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_badsig, NULL); if (conf->conf_dolog) { syslog(LOG_NOTICE, "%s: bad signature data", JOBID(dfc->mctx_jobid)); } replytxt = "bad DKIM signature data"; memset(smtpprefix, '\0', sizeof smtpprefix); sig = dkim_getsignature(dkim); (void) dkim_sig_getreportinfo(dkim, sig, NULL, 0, NULL, 0, NULL, 0, smtpprefix, sizeof smtpprefix, NULL); break; case DKIM_STAT_NOSIG: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_nosig, NULL); if (conf->conf_dolog) { if (conf->conf_logwhy || retcode != SMFIS_ACCEPT) { syslog(retcode == SMFIS_ACCEPT ? LOG_DEBUG : LOG_NOTICE, "%s: no signature data", JOBID(dfc->mctx_jobid)); } } replytxt = "no DKIM signature data"; break; case DKIM_STAT_NORESOURCE: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_internal, NULL); if (conf->conf_capture) dfc->mctx_capture = TRUE; if (conf->conf_dolog) { const char *err = NULL; if (dkim != NULL) err = dkim_geterror(dkim); if (err == NULL) err = strerror(errno); syslog(LOG_ERR, "%s: %s%sresource unavailable: %s", JOBID(dfc->mctx_jobid), where == NULL ? "" : where, where == NULL ? "" : ": ", err); } replytxt = "resource unavailable"; break; case DKIM_STAT_CANTVRFY: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_badsig, NULL); if (conf->conf_dolog && dkim != NULL) { const char *err = NULL; err = dkim_geterror(dkim); if (err == NULL) err = "unknown cause"; syslog(LOG_ERR, "%s: signature processing failed: %s", JOBID(dfc->mctx_jobid), err); } replytxt = "DKIM signature processing failed"; break; case DKIM_STAT_REVOKED: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_badsig, NULL); if (conf->conf_dolog) { u_char *selector = NULL; u_char *domain = NULL; u_char *algorithm = NULL; DKIM_SIGINFO *sig; sig = dkim_getsignature(dkim); if (sig != NULL) { selector = dkim_sig_getselector(sig); domain = dkim_sig_getdomain(sig); algorithm = dkim_sig_getalgorithm(sig); } if (selector != NULL && domain != NULL) { syslog(LOG_NOTICE, "%s: key revoked (s=%s, d=%s, a=%s)", JOBID(dfc->mctx_jobid), selector, domain, algorithm); } } break; case DKIM_STAT_KEYFAIL: case DKIM_STAT_NOKEY: if (status == DKIM_STAT_KEYFAIL) { retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_dnserr, NULL); } else { retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_nokey, NULL); } if (conf->conf_dolog) { const char *err = NULL; u_char *selector = NULL; u_char *domain = NULL; DKIM_SIGINFO *sig; err = dkim_geterror(dkim); sig = dkim_getsignature(dkim); if (sig != NULL) { selector = dkim_sig_getselector(sig); domain = dkim_sig_getdomain(sig); } if (selector != NULL && domain != NULL) { syslog(LOG_ERR, "%s: key retrieval failed (s=%s, d=%s)%s%s", JOBID(dfc->mctx_jobid), selector, domain, err == NULL ? "" : ": ", err == NULL ? "" : err); } else { syslog(LOG_ERR, "%s: key retrieval failed%s%s", JOBID(dfc->mctx_jobid), err == NULL ? "" : ": ", err == NULL ? "" : err); } } replytxt = "DKIM key retrieval failed"; break; case DKIM_STAT_SYNTAX: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_badsig, NULL); if (conf->conf_dolog) { const char *err = NULL; if (dkim != NULL) err = dkim_geterror(dkim); if (err == NULL) err = "unspecified"; syslog(LOG_ERR, "%s: syntax error: %s", JOBID(dfc->mctx_jobid), err); } replytxt = "DKIM signature syntax error"; break; case DKIM_STAT_SIGGEN: retcode = dkimf_miltercode(ctx, conf->conf_handling.hndl_siggen, NULL); if (conf->conf_dolog) { const char *err = NULL; if (dkim != NULL) err = dkim_geterror(dkim); if (err == NULL) err = "unspecified"; syslog(LOG_ERR, "%s: signature generation error: %s", JOBID(dfc->mctx_jobid), err); } replytxt = "DKIM signing error"; break; } switch (retcode) { case SMFIS_REJECT: rcode = "550"; xcode = "5.7.0"; break; case SMFIS_TEMPFAIL: rcode = "451"; if (status == DKIM_STAT_KEYFAIL || status == DKIM_STAT_NOKEY) xcode = "4.7.5"; else xcode = "4.7.0"; break; default: break; } if (rcode != NULL && xcode != NULL && replytxt != NULL) { char replybuf[BUFRSZ]; if (smtpprefix[0] == '\0') { strlcpy(replybuf, replytxt, sizeof replybuf); } else { snprintf(replybuf, sizeof replybuf, "%s: %s", smtpprefix, replytxt); } (void) dkimf_setreply(ctx, rcode, xcode, replybuf); } return retcode; } /* ** DKIMF_FINDHEADER -- find a header ** ** Parameters: ** dfc -- filter context ** hname -- name of the header of interest ** instance -- which instance is wanted (0 = first) ** ** Return value: ** Header handle, or NULL if not found. ** ** Notes: ** Negative values of "instance" search backwards from the end. */ static Header dkimf_findheader(msgctx dfc, char *hname, int instance) { Header hdr; assert(dfc != NULL); assert(hname != NULL); if (instance < 0) hdr = dfc->mctx_hqtail; else hdr = dfc->mctx_hqhead; while (hdr != NULL) { if (strcasecmp(hdr->hdr_hdr, hname) == 0) { if (instance == 0 || instance == -1) return hdr; else if (instance > 0) instance--; else instance++; } if (instance < 0) hdr = hdr->hdr_prev; else hdr = hdr->hdr_next; } return NULL; } /* ** DKIMF_APPLY_SIGNTABLE -- apply the signing table to a message ** ** Parameters: ** dfc -- message context ** keydb -- database handle for key table ** signdb -- database handle for signing table ** user -- userid (local-part) ** domain -- domain ** errkey -- where to write the name of a key that failed ** errlen -- bytes available at "errkey" ** multisig -- apply multiple signature logic ** ** Return value: ** >= 0 -- number of signatures added ** -1 -- signing table read error ** -2 -- unknown key ** -3 -- key load error */ static int dkimf_apply_signtable(struct msgctx *dfc, DKIMF_DB keydb, DKIMF_DB signdb, unsigned char *user, unsigned char *domain, char *errkey, size_t errlen, _Bool multisig) { _Bool found; int nfound = 0; char keyname[BUFRSZ + 1]; u_char tmp[BUFRSZ + 1]; assert(dfc != NULL); assert(keydb != NULL); assert(signdb != NULL); assert(user != NULL); assert(domain != NULL); if (dkimf_db_type(signdb) == DKIMF_DB_TYPE_REFILE) { int status; void *ctx = NULL; struct dkimf_db_data dbd[2]; char addr[MAXADDRESS + 1]; u_char signer[MAXADDRESS + 1]; snprintf(addr, sizeof addr, "%s@%s", user, domain); memset(&dbd, '\0', sizeof dbd); dbd[0].dbdata_buffer = keyname; dbd[1].dbdata_buffer = (char *) signer; dbd[1].dbdata_flags = DKIMF_DB_DATA_OPTIONAL; /* walk RE set, find match(es), make request(s) */ for (;;) { memset(keyname, '\0', sizeof keyname); dbd[0].dbdata_buflen = sizeof keyname - 1; memset(signer, '\0', sizeof signer); dbd[1].dbdata_buflen = sizeof signer - 1; status = dkimf_db_rewalk(signdb, addr, dbd, 2, &ctx); if (status == -1) return -1; else if (status == 1) break; if (keyname[0] == '%' && keyname[1] == '\0') strlcpy(keyname, domain, sizeof keyname); dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } } else { int status; char *p; char tmpaddr[MAXADDRESS + 1]; u_char signer[MAXADDRESS + 1]; struct dkimf_db_data req[2]; memset(&req, '\0', sizeof req); memset(keyname, '\0', sizeof keyname); memset(signer, '\0', sizeof signer); req[0].dbdata_buffer = keyname; req[0].dbdata_buflen = sizeof keyname - 1; req[1].dbdata_buffer = (char *) signer; req[1].dbdata_buflen = sizeof signer - 1; req[1].dbdata_flags = DKIMF_DB_DATA_OPTIONAL; /* first try full "user@host" */ snprintf(tmpaddr, sizeof tmpaddr, "%s@%s", user, domain); found = FALSE; status = dkimf_db_get(signdb, tmpaddr, strlen(tmpaddr), req, 2, &found); if (status != 0 || (found && (req[0].dbdata_buflen == 0 || req[0].dbdata_buflen == (size_t) -1))) { if (status != 0 && dolog) dkimf_db_error(signdb, tmpaddr); return -1; } else if (found) { if (keyname[0] == '%' && keyname[1] == '\0') strlcpy(keyname, domain, sizeof keyname); dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } /* now just "host" */ found = FALSE; req[0].dbdata_buflen = sizeof keyname - 1; req[1].dbdata_buflen = sizeof signer - 1; memset(keyname, '\0', sizeof keyname); memset(signer, '\0', sizeof signer); status = dkimf_db_get(signdb, domain, strlen((char *) domain), req, 2, &found); if (status != 0 || (found && (req[0].dbdata_buflen == 0 || req[0].dbdata_buflen == (size_t) -1))) { if (status != 0 && dolog) dkimf_db_error(signdb, (char *) domain); return -1; } else if (found) { if (keyname[0] == '%' && keyname[1] == '\0') strlcpy(keyname, domain, sizeof keyname); dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } /* next "user@.domain" and ".domain", degrading */ for (p = strchr((char *) domain, '.'); p != NULL; p = strchr(p + 1, '.')) { snprintf(tmpaddr, sizeof tmpaddr, "%s@%s", user, p); found = FALSE; req[0].dbdata_buflen = sizeof keyname - 1; req[1].dbdata_buflen = sizeof signer - 1; memset(keyname, '\0', sizeof keyname); memset(signer, '\0', sizeof signer); status = dkimf_db_get(signdb, tmpaddr, strlen(tmpaddr), req, 2, &found); if (status != 0 || (found && (req[0].dbdata_buflen == 0 || req[0].dbdata_buflen == (size_t) -1))) { if (status != 0 && dolog) dkimf_db_error(signdb, tmpaddr); return -1; } else if (found) { if (keyname[0] == '%' && keyname[1] == '\0') { strlcpy(keyname, domain, sizeof keyname); } dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } found = FALSE; req[0].dbdata_buflen = sizeof keyname - 1; req[1].dbdata_buflen = sizeof signer - 1; memset(keyname, '\0', sizeof keyname); memset(signer, '\0', sizeof signer); status = dkimf_db_get(signdb, p, strlen(p), req, 2, &found); if (status != 0 || (found && (req[0].dbdata_buflen == 0 || req[0].dbdata_buflen == (size_t) -1))) { if (status != 0 && dolog) dkimf_db_error(signdb, p); return -1; } else if (found) { if (keyname[0] == '%' && keyname[1] == '\0') { strlcpy(keyname, domain, sizeof keyname); } dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } } /* now "user@*" */ snprintf(tmpaddr, sizeof tmpaddr, "%s@*", user); found = FALSE; req[0].dbdata_buflen = sizeof keyname - 1; req[1].dbdata_buflen = sizeof signer - 1; memset(keyname, '\0', sizeof keyname); memset(signer, '\0', sizeof signer); status = dkimf_db_get(signdb, tmpaddr, strlen(tmpaddr), req, 2, &found); if (status != 0 || (found && (req[0].dbdata_buflen == 0 || req[0].dbdata_buflen == (size_t) -1))) { if (status != 0 && dolog) dkimf_db_error(signdb, tmpaddr); return -1; } else if (found) { if (keyname[0] == '%' && keyname[1] == '\0') strlcpy(keyname, domain, sizeof keyname); dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } /* finally just "*" */ found = FALSE; req[0].dbdata_buflen = sizeof keyname - 1; req[1].dbdata_buflen = sizeof signer - 1; memset(keyname, '\0', sizeof keyname); memset(signer, '\0', sizeof signer); status = dkimf_db_get(signdb, "*", 1, req, 2, &found); if (status != 0 || (found && (req[0].dbdata_buflen == 0 || req[0].dbdata_buflen == (size_t) -1))) { if (status != 0 && dolog) dkimf_db_error(signdb, "*"); return -1; } else if (found) { if (keyname[0] == '%' && keyname[1] == '\0') strlcpy(keyname, domain, sizeof keyname); dkimf_reptoken(tmp, sizeof tmp, signer, domain); status = dkimf_add_signrequest(dfc, keydb, keyname, (char *) tmp, (ssize_t) -1); if (status != 0 && errkey != NULL) strlcpy(errkey, keyname, errlen); if (status == 1) return -2; else if (status == 2 || status == 3 || status == -1) return -3; nfound++; if (!multisig) return nfound; } } return nfound; } /* ** DKIMF_SIGREPORT -- generate a report on signature failure (if possible) ** ** Parameters: ** cc -- connection context ** conf -- current configuration object ** hostname -- hostname to use for reporting MTA ** ** Return value: ** None. */ static void dkimf_sigreport(connctx cc, struct dkimf_config *conf, char *hostname) { _Bool sendreport = FALSE; int bfd = -1; int hfd = -1; int status; int arftype = ARF_TYPE_UNKNOWN; int arfdkim = ARF_DKIMF_UNKNOWN; u_int pct = 100; u_int rn; time_t now; DKIM_STAT repstatus; char *p; char *last; FILE *out; msgctx dfc; DKIM_SIGINFO *sig; struct Header *hdr; struct tm tm; char ipstr[DKIM_MAXHOSTNAMELEN + 1]; char opts[BUFRSZ]; char fmt[BUFRSZ]; u_char addr[MAXADDRESS + 1]; assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc->mctx_dkimv != NULL); assert(conf != NULL); assert(hostname != NULL); memset(addr, '\0', sizeof addr); memset(opts, '\0', sizeof opts); sig = dkim_getsignature(dfc->mctx_dkimv); /* if no report is possible, just skip it */ repstatus = dkim_sig_getreportinfo(dfc->mctx_dkimv, sig, &hfd, &bfd, (u_char *) addr, sizeof addr, (u_char *) opts, sizeof opts, NULL, 0, &pct); if (repstatus != DKIM_STAT_OK || addr[0] == '\0') return; if (pct < 100) { rn = random() % 100; if (rn > pct) return; } /* ignore any domain name in "r=" */ p = strchr((char *) addr, '@'); if (p != NULL) *p = '\0'; /* ensure the event being reported was requested */ if (opts[0] == '\0') { sendreport = TRUE; } else { for (p = strtok_r(opts, ":", &last); p != NULL; p = strtok_r(NULL, ":", &last)) { if (strcasecmp(p, ARF_OPTIONS_DKIM_ALL) == 0) { sendreport = TRUE; break; } else if (strcasecmp(p, ARF_OPTIONS_DKIM_SYNTAX) == 0) { int err; err = dkim_sig_geterror(sig); if (err == DKIM_SIGERROR_TIMESTAMPS || err == DKIM_SIGERROR_INVALID_HC || err == DKIM_SIGERROR_INVALID_BC || err == DKIM_SIGERROR_MISSING_A || err == DKIM_SIGERROR_INVALID_A || err == DKIM_SIGERROR_MISSING_H || err == DKIM_SIGERROR_INVALID_L || err == DKIM_SIGERROR_INVALID_Q || err == DKIM_SIGERROR_INVALID_QO || err == DKIM_SIGERROR_MISSING_D || err == DKIM_SIGERROR_EMPTY_D || err == DKIM_SIGERROR_MISSING_S || err == DKIM_SIGERROR_EMPTY_S || err == DKIM_SIGERROR_MISSING_B || err == DKIM_SIGERROR_EMPTY_B || err == DKIM_SIGERROR_CORRUPT_B || err == DKIM_SIGERROR_MISSING_BH || err == DKIM_SIGERROR_EMPTY_BH || err == DKIM_SIGERROR_CORRUPT_BH || err == DKIM_SIGERROR_EMPTY_H || err == DKIM_SIGERROR_INVALID_H || err == DKIM_SIGERROR_TOOLARGE_L || err == DKIM_SIGERROR_MISSING_V || err == DKIM_SIGERROR_EMPTY_V) { sendreport = TRUE; break; } } else if (strcasecmp(p, ARF_OPTIONS_DKIM_EXPIRED) == 0) { if (dkim_sig_geterror(sig) == DKIM_SIGERROR_EXPIRED) { sendreport = TRUE; break; } } else if (strcasecmp(p, ARF_OPTIONS_DKIM_VERIFY) == 0) { if (dkim_sig_geterror(sig) == DKIM_SIGERROR_BADSIG || dkim_sig_getbh(sig) == DKIM_SIGBH_MISMATCH) { sendreport = TRUE; break; } } else if (strcasecmp(p, ARF_OPTIONS_DKIM_DNS) == 0) { int err; err = dkim_sig_geterror(sig); if (err == DKIM_SIGERROR_NOKEY || err == DKIM_SIGERROR_DNSSYNTAX || err == DKIM_SIGERROR_KEYFAIL || err == DKIM_SIGERROR_KEYDECODE || err == DKIM_SIGERROR_MULTIREPLY) { sendreport = TRUE; break; } } else if (strcasecmp(p, ARF_OPTIONS_DKIM_POLICY) == 0) { int err; err = dkim_sig_geterror(sig); if (err == DKIM_SIGERROR_MBSFAILED) { sendreport = TRUE; break; } } else if (strcasecmp(p, ARF_OPTIONS_DKIM_OTHER) == 0) { int err; err = dkim_sig_geterror(sig); if (err == DKIM_SIGERROR_SUBDOMAIN || err == DKIM_SIGERROR_KEYVERSION || err == DKIM_SIGERROR_KEYUNKNOWNHASH || err == DKIM_SIGERROR_KEYHASHMISMATCH || err == DKIM_SIGERROR_NOTEMAILKEY || err == DKIM_SIGERROR_KEYTYPEMISSING || err == DKIM_SIGERROR_KEYTYPEUNKNOWN || err == DKIM_SIGERROR_KEYREVOKED) { sendreport = TRUE; break; } } } } if (!sendreport) return; #ifdef HAVE_CURL_EASY_STRERROR if (conf->conf_smtpuri != NULL) { int fd; char path[MAXPATHLEN + 1]; snprintf(path, sizeof path, "%s/%s.XXXXXX", conf->conf_tmpdir, progname); fd = mkstemp(path); if (fd < 0) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: mkstemp(): %s", dfc->mctx_jobid, strerror(errno)); } return; } unlink(path); out = fdopen(fd, "w"); if (out == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: fdopen(): %s", dfc->mctx_jobid, strerror(errno)); } close(fd); return; } } else { out = popen(reportcmd, "w"); if (out == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: popen(): %s", dfc->mctx_jobid, strerror(errno)); } return; } } #else /* HAVE_CURL_EASY_STRERROR */ out = popen(reportcmd, "w"); if (out == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: popen(): %s", dfc->mctx_jobid, strerror(errno)); } return; } #endif /* HAVE_CURL_EASY_STRERROR */ /* determine the type of ARF failure and, if needed, a DKIM fail code */ arftype = dkimf_arftype(dfc); if (arftype == ARF_TYPE_AUTHFAIL) arfdkim = dkimf_arfdkim(dfc); /* From: */ fprintf(out, "From: %s\n", reportaddr); /* To: */ fprintf(out, "To: %s@%s\n", addr, dkim_sig_getdomain(sig)); /* Bcc: */ if (conf->conf_reportaddrbcc != NULL) fprintf(out, "Bcc: %s\n", conf->conf_reportaddrbcc); /* Date: */ memset(fmt, '\0', sizeof fmt); (void) time(&now); (void) localtime_r(&now, &tm); (void) strftime(fmt, sizeof fmt, "%a, %e %b %Y %H:%M:%S %z (%Z)", &tm); fprintf(out, "Date: %s\n", fmt); /* Subject: */ fprintf(out, "Subject: DKIM failure report for %s\n", dfc->mctx_jobid); /* MIME stuff */ fprintf(out, "MIME-Version: 1.0\n"); fprintf(out, "Content-Type: multipart/report; report-type=feedback-report;\n\tboundary=\"dkimreport/%s/%s\"", hostname, dfc->mctx_jobid); /* ok, now then... */ fprintf(out, "\n"); /* first part: a text blob explaining what this is */ fprintf(out, "--dkimreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: text/plain\n"); fprintf(out, "\n"); fprintf(out, "DKIM failure report for job %s on %s\n\n", dfc->mctx_jobid, hostname); fprintf(out, "The canonicalized form of the failed message's header and body are\nattached.\n"); fprintf(out, "\n"); /* second part: formatted gunk */ memset(ipstr, '\0', sizeof ipstr); switch (cc->cctx_ip.ss_family) { case AF_INET: { struct sockaddr_in sin4; memcpy(&sin4, &cc->cctx_ip, sizeof sin4); (void) inet_ntop(AF_INET, &sin4.sin_addr, ipstr, sizeof ipstr); break; } #ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 sin6; memcpy(&sin6, &cc->cctx_ip, sizeof sin6); (void) inet_ntop(AF_INET6, &sin6.sin6_addr, ipstr, sizeof ipstr); break; } #endif /* AF_INET6 */ } hdr = dkimf_findheader(dfc, (char *) "Message-ID", 0); fprintf(out, "--dkimreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: message/feedback-report\n"); fprintf(out, "\n"); fprintf(out, "User-Agent: %s/%s\n", DKIMF_PRODUCTNS, VERSION); fprintf(out, "Version: %s\n", ARF_VERSION); fprintf(out, "Original-Envelope-Id: %s\n", dfc->mctx_jobid); fprintf(out, "Original-Mail-From: %s\n", dfc->mctx_envfrom); fprintf(out, "Reporting-MTA: %s\n", hostname); fprintf(out, "Source-IP: %s\n", ipstr); fprintf(out, "Message-ID:%s%s\n", cc->cctx_noleadspc ? "" : " ", hdr == NULL ? "(none)" : hdr->hdr_val); fprintf(out, "Arrival-Date: %s\n", fmt); fprintf(out, "Reported-Domain: %s\n", dkim_sig_getdomain(sig)); fprintf(out, "Delivery-Result: other\n"); fprintf(out, "Feedback-Type: %s\n", arf_type_string(arftype)); if (arftype == ARF_TYPE_AUTHFAIL) { fprintf(out, "Auth-Failure: "); if (dkim_sig_getbh(sig) == DKIM_SIGBH_MISMATCH) { fprintf(out, "bodyhash\n"); } else { const char *tmperror; switch (dkim_sig_geterror(sig)) { case DKIM_SIGERROR_KEYREVOKED: fprintf(out, "revoked\n"); break; default: tmperror = dkim_sig_geterrorstr(dkim_sig_geterror(sig)); fprintf(out, "signature"); if (tmperror != NULL) fprintf(out, " (%s)", tmperror); fprintf(out, "\n"); break; } } memset(addr, '\0', sizeof addr); dkim_sig_getidentity(dfc->mctx_dkimv, sig, addr, sizeof addr - 1); /* fprintf(out, "Authentication-Results: %s\n", ...); */ fprintf(out, "DKIM-Failure: %s\n", arf_dkim_failure_string(arfdkim)); fprintf(out, "DKIM-Domain: %s\n", dkim_sig_getdomain(sig)); fprintf(out, "DKIM-Selector: %s\n", dkim_sig_getselector(sig)); fprintf(out, "DKIM-Identity: %s\n", addr); if (hfd != -1) { fprintf(out, "DKIM-Canonicalized-Header: "); (void) dkimf_base64_encode_file(hfd, out, 4, 75, 27); fprintf(out, "\n"); } if (bfd != -1) { fprintf(out, "DKIM-Canonicalized-Body: "); (void) dkimf_base64_encode_file(bfd, out, 4, 75, 25); fprintf(out, "\n"); } } fprintf(out, "\n"); /* third part: header block */ fprintf(out, "--dkimreport/%s/%s\n", hostname, dfc->mctx_jobid); fprintf(out, "Content-Type: text/rfc822-headers\n"); fprintf(out, "\n"); for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { fprintf(out, "%s:%s%s\n", hdr->hdr_hdr, cc->cctx_noleadspc ? "" : " ", hdr->hdr_val); } /* end */ fprintf(out, "\n--dkimreport/%s/%s--\n", hostname, dfc->mctx_jobid); /* send it */ #ifdef HAVE_CURL_EASY_SETOPT if (conf->conf_smtpuri != NULL) { CURLcode cc; CURL *curl; struct curl_slist *rcpts = NULL; char dest[MAXADDRESS + 1]; (void) fseek(out, SEEK_SET, 0); curl = curl_easy_init(); if (curl == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: curl_easy_init() failed", dfc->mctx_jobid); } } else { cc = curl_easy_setopt(curl, CURLOPT_URL, conf->conf_smtpuri); if (cc == CURLE_OK) { cc = curl_easy_setopt(curl, CURLOPT_READDATA, out); } if (cc == CURLE_OK) { cc = curl_easy_setopt(curl, CURLOPT_MAIL_FROM, reportaddr); } if (cc == CURLE_OK) { snprintf(dest, sizeof dest, "%s@%s", addr, dkim_sig_getdomain(sig)); rcpts = curl_slist_append(rcpts, dest); cc = curl_easy_setopt(curl, CURLOPT_MAIL_RCPT, rcpts); } if (cc != CURLE_OK) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: curl_easy_setopt() failed", dfc->mctx_jobid); } } else { cc = curl_easy_perform(curl); if (cc != CURLE_OK && conf->conf_dolog) { syslog(LOG_ERR, "%s: curl_easy_perform() to %s failed: %s", dfc->mctx_jobid, dest, curl_easy_strerror(cc)); } } curl_slist_free_all(rcpts); curl_easy_cleanup(curl); } } else { status = pclose(out); if (status != 0 && conf->conf_dolog) { syslog(LOG_ERR, "%s: pclose(): returned status %d", dfc->mctx_jobid, status); } } #else /* HAVE_CURL_EASY_SETOPT */ status = pclose(out); if (status != 0 && conf->conf_dolog) { syslog(LOG_ERR, "%s: pclose(): returned status %d", dfc->mctx_jobid, status); } #endif /* HAVE_CURL_EASY_SETOPT */ } /* ** DKIMF_AR_ALL_SIGS -- append Authentication-Results items for all signatures ** ** Parameters: ** hdr -- header buffer ** hdrlen -- size of header buffer ** tmpstr -- a dstring to construct the result ** dkim -- DKIM verification handle ** conf -- config object ** status -- message context status (may be updated) ** ** Return value: ** FALSE iff the filter should reject the message based on results. */ void dkimf_ar_all_sigs(char *hdr, size_t hdrlen, struct dkimf_dstring *tmpstr, DKIM *dkim, struct dkimf_config *conf, int *status) { int nsigs; DKIM_STAT dstatus; DKIM_SIGINFO **sigs; assert(hdr != NULL); assert(tmpstr != NULL); assert(dkim != NULL); assert(conf != NULL); assert(status != NULL); dstatus = dkim_getsiglist(dkim, &sigs, &nsigs); if (dstatus == DKIM_STAT_OK) { int c; int sigerror; DKIM_STAT ts; u_int keybits; size_t ssl; char *result; char *dnssec; char *domain; char *selector; char *algorithm; char ss[BUFRSZ + 1]; char tmp[BUFRSZ + 1]; char val[MAXADDRESS + 1]; char comment[BUFRSZ + 1]; for (c = 0; c < nsigs; c++) { dnssec = NULL; memset(comment, '\0', sizeof comment); sigerror = dkim_sig_geterror(sigs[c]); if (dkim_sig_getkeysize(sigs[c], &keybits) != DKIM_STAT_OK) keybits = 0; if (conf->conf_noheaderb) { ts = -1; } else { ssl = sizeof ss - 1; ts = dkim_get_sigsubstring(dkim, sigs[c], ss, &ssl); } if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0 && dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH) { result = "pass"; } else if (sigerror == DKIM_SIGERROR_MULTIREPLY || sigerror == DKIM_SIGERROR_KEYFAIL || sigerror == DKIM_SIGERROR_DNSSYNTAX) { result = "temperror"; } else if (sigerror == DKIM_SIGERROR_KEYTOOSMALL) { const char *err; result = "policy"; err = dkim_sig_geterrorstr(dkim_sig_geterror(sigs[c])); if (err != NULL) { snprintf(comment, sizeof comment, " reason=\"%s\"", err); } } else if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PROCESSED) != 0 && ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) == 0 || dkim_sig_getbh(sigs[c]) != DKIM_SIGBH_MATCH)) { const char *err; result = "fail"; err = dkim_sig_geterrorstr(dkim_sig_geterror(sigs[c])); if (err != NULL) { snprintf(comment, sizeof comment, " reason=\"%s\"", err); } } else if (sigerror != DKIM_SIGERROR_UNKNOWN && sigerror != DKIM_SIGERROR_OK) { result = "permerror"; } else { result = "neutral"; } dnssec = NULL; switch (dkim_sig_getdnssec(sigs[c])) { case DKIM_DNSSEC_UNKNOWN: break; case DKIM_DNSSEC_INSECURE: dnssec = "unprotected"; if (conf->conf_unprotectedkey == DKIMF_KEYACTIONS_FAIL) { *status = DKIMF_STATUS_BAD; result = "policy"; } else if (conf->conf_unprotectedkey == DKIMF_KEYACTIONS_NEUTRAL) { *status = DKIMF_STATUS_VERIFYERR; result = "neutral"; } break; case DKIM_DNSSEC_BOGUS: dnssec = "bogus"; if (conf->conf_boguskey == DKIMF_KEYACTIONS_FAIL) { *status = DKIMF_STATUS_BAD; } else if (conf->conf_boguskey == DKIMF_KEYACTIONS_NEUTRAL) { *status = DKIMF_STATUS_VERIFYERR; result = "neutral"; } break; case DKIM_DNSSEC_SECURE: dnssec = "secure"; break; } memset(val, '\0', sizeof val); (void) dkim_sig_getidentity(dkim, sigs[c], val, sizeof val - 1); domain = dkim_sig_getdomain(sigs[c]); selector = dkim_sig_getselector(sigs[c]); algorithm = dkim_sig_getalgorithm(sigs[c]); dkimf_dstring_blank(tmpstr); dkimf_dstring_printf(tmpstr, "%s%s", c == 0 ? "" : ";", DELIMITER); dkimf_dstring_printf(tmpstr, "dkim=%s", result); dkimf_dstring_printf(tmpstr, comment); if (keybits > 0) { dkimf_dstring_printf(tmpstr, " (%u-bit key%s%s)", keybits, dnssec == NULL ? "" : "; ", dnssec == NULL ? "" : dnssec); } dkimf_dstring_printf(tmpstr, " header.d=%s header.i=%s header.a=%s header.s=%s", domain, val, algorithm, selector); if (ts == DKIM_STAT_OK) { dkimf_dstring_printf(tmpstr, " header.b=%s", ss); } strlcat(hdr, dkimf_dstring_get(tmpstr), hdrlen); } } } #ifdef _FFR_CONDITIONAL /* ** DKIMF_CHECK_CONDITIONAL -- apply any conditional signature needed ** ** Parameters: ** dfc -- message context ** conf -- configuration ** sr -- a signing request ** ** Return value: ** Status from dkim_conditional, if any. */ static DKIM_STAT dkimf_check_conditional(struct msgctx *dfc, struct dkimf_config *conf, struct signreq *sr) { _Bool found; size_t len; DKIM_STAT status; struct dkimf_dstring *dstr = NULL; struct addrlist *a; struct signreq *newsr_head = NULL; struct signreq *newsr_tail = NULL; char *at; dstr = dkimf_dstring_new(BUFRSZ, 0); dkimf_dstring_cat(dstr, dfc->mctx_domain); dkimf_dstring_cat1(dstr, ':'); len = dkimf_dstring_len(dstr); for (a = dfc->mctx_rcptlist; a != NULL; a = a->a_next) { dkimf_dstring_chop(dstr, len); at = strchr(a->a_addr, '@'); if (at == NULL) continue; dkimf_dstring_cat(dstr, at + 1); /* ** Look for from/to pair in conditional DB; if found, ** request a conditional signature with d= from-domain ** and !cd= recipient domain, for now with l=0 */ found = FALSE; if (dkimf_db_get(conf->conf_conditionaldb, dkimf_dstring_get(dstr), 0, NULL, 0, &found) != 0) { if (conf->conf_dolog) syslog(LOG_ERR, "dkimf_db_get() failed"); return DKIM_STAT_INTERNAL; } if (found) { int status; struct signreq *newsr; void *keydata; unsigned char *sdomain; unsigned char *selector; newsr = (struct signreq *) malloc(sizeof(struct signreq)); if (newsr == NULL) { if (conf->conf_dolog) syslog(LOG_ERR, "malloc() failed"); return DKIM_STAT_NORESOURCE; } memset(newsr, '\0', sizeof(*newsr)); if (sr->srq_keydata == NULL) { keydata = (dkim_sigkey_t) conf->conf_seckey; sdomain = dfc->mctx_domain; selector = conf->conf_selector; } else { keydata = sr->srq_keydata; sdomain = sr->srq_domain; selector = sr->srq_selector; } newsr->srq_dkim = dkim_sign(conf->conf_libopendkim, dfc->mctx_jobid, NULL, keydata, selector, sdomain, dfc->mctx_hdrcanon, dfc->mctx_bodycanon, dfc->mctx_signalg, 0, &status); if (status != DKIM_STAT_OK) { if (conf->conf_dolog) syslog(LOG_ERR, "dkim_sign() failed"); free(newsr); return DKIM_STAT_INTERNAL; } status = dkim_conditional(newsr->srq_dkim, at + 1); if (status != DKIM_STAT_OK) { free(newsr); return status; } if (newsr_head == NULL) { newsr_head = newsr; newsr_tail = newsr; } else { newsr_tail->srq_next = newsr; newsr_tail = newsr; } } } if (dfc->mctx_srtail != NULL && newsr_head != NULL) { dfc->mctx_srtail->srq_next = newsr_head; dfc->mctx_srtail = newsr_tail; } dkimf_dstring_free(dstr); return DKIM_STAT_OK; } #endif /* _FFR_CONDITIONAL */ /* ** END private section ** ================================================================== ** BEGIN milter section */ #if SMFI_VERSION >= 0x01000000 /* ** MLFI_NEGOTIATE -- handler called on new SMTP connection to negotiate ** MTA options ** ** Parameters: ** ctx -- milter context ** f0 -- actions offered by the MTA ** f1 -- protocol steps offered by the MTA ** f2 -- reserved for future extensions ** f3 -- reserved for future extensions ** pf0 -- actions requested by the milter ** pf1 -- protocol steps requested by the milter ** pf2 -- reserved for future extensions ** pf3 -- reserved for future extensions ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_negotiate(SMFICTX *ctx, unsigned long f0, unsigned long f1, unsigned long f2, unsigned long f3, unsigned long *pf0, unsigned long *pf1, unsigned long *pf2, unsigned long *pf3) { unsigned long reqactions = SMFIF_ADDHDRS; # if defined(SMFIF_SETSYMLIST) && defined(HAVE_SMFI_SETSYMLIST) unsigned long wantactions = (SMFIF_SETSYMLIST); # else /* defined(SMFIF_SETSYMLIST) && defined(HAVE_SMFI_SETSYMLIST) */ unsigned long wantactions = 0; # endif /* defined(SMFIF_SETSYMLIST) && defined(HAVE_SMFI_SETSYMLIST) */ unsigned long protosteps = (SMFIP_NOHELO | SMFIP_NOUNKNOWN | SMFIP_NODATA | SMFIP_SKIP ); connctx cc; struct dkimf_config *conf; dkimf_config_reload(); /* initialize connection context */ cc = malloc(sizeof(struct connctx)); if (cc == NULL) { if (curconf->conf_dolog) { syslog(LOG_ERR, "mlfi_negotiate(): malloc(): %s", strerror(errno)); } return SMFIS_TEMPFAIL; } memset(cc, '\0', sizeof(struct connctx)); pthread_mutex_lock(&conf_lock); cc->cctx_config = curconf; curconf->conf_refcnt++; conf = curconf; pthread_mutex_unlock(&conf_lock); /* verify the actions we need are available */ if (conf->conf_remarall || !conf->conf_keepar || # ifdef _FFR_IDENTITY_HEADER conf->conf_rmidentityhdr || # endif /* _FFR_IDENTITY_HEADER */ # ifdef _FFR_VBR conf->conf_vbr_purge || # endif /* _FFR_VBR */ conf->conf_remsigs) reqactions |= SMFIF_CHGHDRS; # ifdef SMFIF_QUARANTINE if (conf->conf_capture) reqactions |= SMFIF_QUARANTINE; # endif /* SMFIF_QUARANTINE */ if (conf->conf_redirect != NULL) { reqactions |= SMFIF_ADDRCPT; reqactions |= SMFIF_DELRCPT; } if ((f0 & reqactions) != reqactions) { if (conf->conf_dolog) { syslog(LOG_ERR, "mlfi_negotiate(): required milter action(s) not available (got 0x%lx, need 0x%lx)", f0, reqactions); } pthread_mutex_lock(&conf_lock); conf->conf_refcnt--; pthread_mutex_unlock(&conf_lock); free(cc); return SMFIS_REJECT; } /* also try to get some nice features */ wantactions = (wantactions & f0); /* set the actions we want */ *pf0 = (reqactions | wantactions); /* disable as many protocol steps we don't need as are available */ *pf1 = (protosteps & f1); # ifdef SMFIP_HDR_LEADSPC /* request preservation of leading spaces if possible */ if ((f1 & SMFIP_HDR_LEADSPC) != 0) { if (cc != NULL) { cc->cctx_noleadspc = TRUE; *pf1 |= SMFIP_HDR_LEADSPC; } } # endif /* SMFIP_HDR_LEADSPC */ *pf2 = 0; *pf3 = 0; /* request macros if able */ # if defined(SMFIF_SETSYMLIST) && defined(HAVE_SMFI_SETSYMLIST) if (conf->conf_macros != NULL && (wantactions & SMFIF_SETSYMLIST) != 0) { int c; char macrolist[BUFRSZ]; memset(macrolist, '\0', sizeof macrolist); strlcpy(macrolist, DKIMF_EOHMACROS, sizeof macrolist); for (c = 0; conf->conf_macros[c] != NULL; c++) { if (macrolist[0] != '\0') strlcat(macrolist, " ", sizeof macrolist); if (strlcat(macrolist, conf->conf_macros[c], sizeof macrolist) >= sizeof macrolist) { if (conf->conf_dolog) { syslog(LOG_ERR, "mlfi_negotiate(): macro list overflow"); } pthread_mutex_lock(&conf_lock); conf->conf_refcnt--; pthread_mutex_unlock(&conf_lock); free(cc); return SMFIS_REJECT; } } if (smfi_setsymlist(ctx, SMFIM_EOH, macrolist) != MI_SUCCESS) { if (conf->conf_dolog) syslog(LOG_ERR, "smfi_setsymlist() failed"); pthread_mutex_lock(&conf_lock); conf->conf_refcnt--; pthread_mutex_unlock(&conf_lock); free(cc); return SMFIS_REJECT; } } # endif /* defined(SMFIF_SETSYMLIST) && defined(HAVE_SMFI_SETSYMLIST) */ /* set "milterv2" flag if SMFIP_SKIP was available */ if ((f1 & SMFIP_SKIP) != 0) cc->cctx_milterv2 = TRUE; (void) dkimf_setpriv(ctx, cc); return SMFIS_CONTINUE; } #endif /* SMFI_VERSION >= 0x01000000 */ /* ** MLFI_CONNECT -- connection handler ** ** Parameters: ** ctx -- milter context ** host -- hostname ** ip -- address, in in_addr form ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_connect(SMFICTX *ctx, char *host, _SOCK_ADDR *ip) { char *err = NULL; connctx cc; struct dkimf_config *conf; dkimf_config_reload(); if (!dkimf_dns_init(curconf->conf_libopendkim, curconf, &err)) { if (curconf->conf_dolog) syslog(LOG_ERR, "can't initialize resolver: %s", err); return SMFIS_TEMPFAIL; } /* copy hostname and IP information to a connection context */ cc = dkimf_getpriv(ctx); if (cc == NULL) { cc = malloc(sizeof(struct connctx)); if (cc == NULL) { pthread_mutex_lock(&conf_lock); if (curconf->conf_dolog) { syslog(LOG_ERR, "%s malloc(): %s", host, strerror(errno)); } pthread_mutex_unlock(&conf_lock); /* XXX result should depend on On-InternalError */ return SMFIS_TEMPFAIL; } memset(cc, '\0', sizeof(struct connctx)); pthread_mutex_lock(&conf_lock); cc->cctx_config = curconf; curconf->conf_refcnt++; conf = curconf; pthread_mutex_unlock(&conf_lock); dkimf_setpriv(ctx, cc); } else { conf = cc->cctx_config; } /* if the client is on an ignored host, then ignore it */ if (conf->conf_peerdb != NULL) { /* try hostname, if available */ if (host != NULL && host[0] != '\0' && host[0] != '[') { dkimf_lowercase((u_char *) host); if (dkimf_checkhost(conf->conf_peerdb, host)) return SMFIS_ACCEPT; } /* try IP address, if available */ if (ip != NULL && (ip->sa_family == AF_INET #ifdef AF_INET6 || ip->sa_family == AF_INET6 #endif /* AF_INET6 */ )) { if (dkimf_checkip(conf->conf_peerdb, ip)) return SMFIS_ACCEPT; } } if (host != NULL) strlcpy(cc->cctx_host, host, sizeof cc->cctx_host); if (ip == NULL) { struct sockaddr_in sin; memset(&sin, '\0', sizeof sin); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); memcpy(&cc->cctx_ip, &sin, sizeof sin); } else if (ip->sa_family == AF_INET) { memcpy(&cc->cctx_ip, ip, sizeof(struct sockaddr_in)); } #ifdef AF_INET6 else if (ip->sa_family == AF_INET6) { memcpy(&cc->cctx_ip, ip, sizeof(struct sockaddr_in6)); } #endif /* AF_INET6 */ cc->cctx_msg = NULL; return SMFIS_CONTINUE; } #if SMFI_VERSION == 2 /* ** MLFI_HELO -- handler for HELO/EHLO command (start of message) ** ** Parameters: ** ctx -- milter context ** helo -- HELO/EHLO parameter ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_helo(SMFICTX *ctx, char *helo) { assert(ctx != NULL); assert(helo != NULL); return SMFIS_CONTINUE; } #endif /* SMFI_VERSION == 2 */ /* ** MLFI_ENVFROM -- handler for MAIL FROM command (start of message) ** ** Parameters: ** ctx -- milter context ** envfrom -- envelope from arguments ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_envfrom(SMFICTX *ctx, char **envfrom) { connctx cc; msgctx dfc; struct dkimf_config *conf; assert(ctx != NULL); assert(envfrom != NULL); cc = (connctx) dkimf_getpriv(ctx); assert(cc != NULL); conf = cc->cctx_config; /* ** Initialize a filter context. */ dkimf_cleanup(ctx); dfc = dkimf_initcontext(conf); if (dfc == NULL) { if (conf->conf_dolog) { syslog(LOG_INFO, "message requeueing (internal error)"); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } if (envfrom[0] != NULL) { size_t len; unsigned char *p; unsigned char *q; strlcpy(dfc->mctx_envfrom, envfrom[0], sizeof dfc->mctx_envfrom); len = strlen(dfc->mctx_envfrom); p = dfc->mctx_envfrom; q = dfc->mctx_envfrom + len - 1; while (len >= 2 && *p == '<' && *q == '>') { p++; q--; len -= 2; } if (p != dfc->mctx_envfrom) { *(q + 1) = '\0'; memmove(dfc->mctx_envfrom, p, len + 1); } } /* ** Save it in this thread's private space. */ cc->cctx_msg = dfc; /* ** Continue processing. */ return SMFIS_CONTINUE; } /* ** MLFI_ENVRCPT -- handler for RCPT TO command ** ** Parameters: ** ctx -- milter context ** envrcpt -- envelope rcpt to arguments ** ** Return value: ** SMFIS_CONTINUE */ sfsistat mlfi_envrcpt(SMFICTX *ctx, char **envrcpt) { connctx cc; msgctx dfc; struct dkimf_config *conf; assert(ctx != NULL); assert(envrcpt != NULL); cc = (connctx) dkimf_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); conf = cc->cctx_config; if (conf->conf_dontsigntodb != NULL || conf->conf_bldb != NULL || conf->conf_redirect != NULL #ifdef _FFR_RESIGN || conf->conf_resigndb != NULL #endif /* _FFR_RESIGN */ #ifdef _FFR_CONDITIONAL || conf->conf_conditionaldb != NULL #endif /* _FFR_CONDITIONAL */ #ifdef USE_LUA || conf->conf_setupscript != NULL || conf->conf_screenscript != NULL || conf->conf_finalscript != NULL # ifdef _FFR_STATSEXT || conf->conf_statsscript != NULL # endif /* _FFR_STATSEXT */ #endif /* USE_LUA */ ) { char *copy; struct addrlist *a; char addr[MAXADDRESS + 1]; strlcpy(addr, envrcpt[0], sizeof addr); dkimf_stripbrackets(addr); copy = strdup(addr); if (copy == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "message requeueing (internal error)"); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } a = (struct addrlist *) malloc(sizeof(struct addrlist)); if (a == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "message requeueing (internal error)"); } free(copy); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } a->a_next = dfc->mctx_rcptlist; a->a_addr = copy; dfc->mctx_rcptlist = a; } return SMFIS_CONTINUE; } /* ** MLFI_HEADER -- handler for mail headers; stores the header in a vector ** of headers for later perusal, removing RFC822 comment ** substrings ** ** Parameters: ** ctx -- milter context ** headerf -- header ** headerv -- value ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_header(SMFICTX *ctx, char *headerf, char *headerv) { #ifdef _FFR_REPLACE_RULES _Bool dorepl = FALSE; #endif /* _FFR_REPLACE_RULES */ msgctx dfc; connctx cc; Header newhdr; struct dkimf_config *conf; assert(ctx != NULL); assert(headerf != NULL); assert(headerv != NULL); cc = (connctx) dkimf_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); conf = cc->cctx_config; /* check for too much header data */ if (conf->conf_maxhdrsz > 0 && dfc->mctx_hdrbytes + strlen(headerf) + strlen(headerv) + 2 > conf->conf_maxhdrsz) { if (conf->conf_dolog) syslog(LOG_NOTICE, "too much header data"); return dkimf_miltercode(ctx, conf->conf_handling.hndl_security, NULL); } /* ** Completely ignore a field name containing a semicolon; this is ** strangely legal by RFC5322, but completely incompatible with DKIM. */ if (strchr(headerf, ';') != NULL) { if (conf->conf_dolog) { syslog(LOG_NOTICE, "ignoring header field '%s'", headerf); } return SMFIS_CONTINUE; } newhdr = (Header) malloc(sizeof(struct Header)); if (newhdr == NULL) { if (conf->conf_dolog) syslog(LOG_ERR, "malloc(): %s", strerror(errno)); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } #ifdef _FFR_REPUTATION # ifdef USE_GNUTLS (void) gnutls_hash(dfc->mctx_hash, headerf, strlen(headerf)); (void) gnutls_hash(dfc->mctx_hash, headerv, strlen(headerv)); # else /* USE_GNUTLS */ SHA1_Update(&dfc->mctx_hash, headerf, strlen(headerf)); SHA1_Update(&dfc->mctx_hash, headerv, strlen(headerv)); # endif /* USE_GNUTLS */ #endif /* _FFR_REPUTATION */ (void) memset(newhdr, '\0', sizeof(struct Header)); newhdr->hdr_hdr = strdup(headerf); if (dfc->mctx_tmpstr == NULL) { dfc->mctx_tmpstr = dkimf_dstring_new(BUFRSZ, 0); if (dfc->mctx_tmpstr == NULL) { if (conf->conf_dolog) syslog(LOG_ERR, "dkimf_dstring_new() failed"); TRYFREE(newhdr->hdr_hdr); free(newhdr); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } else { dkimf_dstring_blank(dfc->mctx_tmpstr); } if (!cc->cctx_noleadspc) { /* ** The sendmail MTA does some minor header rewriting on ** outgoing mail. This makes things slightly prettier for ** the MUA, but these changes are made after this filter has ** already generated and added a signature. As a result, ** verification of the signature will fail because what got ** signed isn't the same as what actually goes out. This ** chunk of code attempts to compensate by arranging to ** feed to the canonicalization algorithms the headers ** exactly as the MTA will modify them, so verification ** should still work. ** ** This is based on experimentation and on reading ** sendmail/headers.c, and may require more tweaking before ** it's precisely right. There are other munges the ** sendmail MTA makes which are not (yet) addressed by this ** code. ** ** This should not be used with sendmail 8.14 and later as ** it is not required; that version of sendmail and ** libmilter handles the munging correctly (by suppressing ** it). */ char *p; p = headerv; while (isascii(*p) && isspace(*p)) p++; dkimf_dstring_copy(dfc->mctx_tmpstr, (u_char *) p); } else { dkimf_dstring_copy(dfc->mctx_tmpstr, (u_char *) headerv); } #ifdef _FFR_REPLACE_RULES if (conf->conf_rephdrsdb == NULL) { dorepl = TRUE; } else { _Bool found; found = FALSE; if (dkimf_db_get(conf->conf_rephdrsdb, (char *) headerf, 0, NULL, 0, &found) != 0) { if (conf->conf_dolog) syslog(LOG_ERR, "dkimf_db_get() failed"); TRYFREE(newhdr->hdr_hdr); free(newhdr); return SMFIS_TEMPFAIL; } dorepl = found; } if (conf->conf_replist != NULL && dorepl) { int status; regmatch_t match; char *str; struct dkimf_dstring *tmphdr = NULL; struct replace *rep; tmphdr = dkimf_dstring_new(BUFRSZ, 0); if (tmphdr == NULL) { if (conf->conf_dolog) syslog(LOG_ERR, "dkimf_dstring_new() failed"); TRYFREE(newhdr->hdr_hdr); free(newhdr); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } for (rep = conf->conf_replist; rep != NULL; rep = rep->repl_next) { str = dkimf_dstring_get(dfc->mctx_tmpstr); for (;;) { status = regexec(&rep->repl_re, str, 1, &match, 0); if (status == REG_NOMATCH) { break; } else if (status != 0) { if (conf->conf_dolog) { syslog(LOG_ERR, "regexec() failed"); } TRYFREE(newhdr->hdr_hdr); free(newhdr); dkimf_dstring_free(tmphdr); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } dkimf_dstring_blank(tmphdr); dkimf_dstring_copy(tmphdr, str); dkimf_dstring_chop(tmphdr, match.rm_so); dkimf_dstring_cat(tmphdr, rep->repl_txt); dkimf_dstring_cat(tmphdr, str + match.rm_eo); dkimf_dstring_blank(dfc->mctx_tmpstr); str = dkimf_dstring_get(tmphdr); dkimf_dstring_cat(dfc->mctx_tmpstr, str); } } dkimf_dstring_free(tmphdr); } #endif /* _FFR_REPLACE_RULES */ newhdr->hdr_val = strdup((char *) dkimf_dstring_get(dfc->mctx_tmpstr)); newhdr->hdr_next = NULL; newhdr->hdr_prev = dfc->mctx_hqtail; if (newhdr->hdr_hdr == NULL || newhdr->hdr_val == NULL) { if (conf->conf_dolog) syslog(LOG_ERR, "malloc(): %s", strerror(errno)); TRYFREE(newhdr->hdr_hdr); TRYFREE(newhdr->hdr_val); TRYFREE(newhdr); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } dfc->mctx_hdrbytes += strlen(newhdr->hdr_hdr) + 1; dfc->mctx_hdrbytes += strlen(newhdr->hdr_val) + 1; if (dfc->mctx_hqhead == NULL) dfc->mctx_hqhead = newhdr; if (dfc->mctx_hqtail != NULL) dfc->mctx_hqtail->hdr_next = newhdr; dfc->mctx_hqtail = newhdr; if (strcasecmp(headerf, conf->conf_selectcanonhdr) == 0) { int c; char *slash; slash = strchr(headerv, '/'); if (slash != NULL) { *slash = '\0'; c = dkimf_lookup_strtoint(headerv, dkimf_canon); if (c != -1) dfc->mctx_hdrcanon = (dkim_canon_t) c; c = dkimf_lookup_strtoint(slash + 1, dkimf_canon); if (c != -1) dfc->mctx_bodycanon = (dkim_canon_t) c; *slash = '/'; } else { c = dkimf_lookup_strtoint(headerv, dkimf_canon); if (c != -1) dfc->mctx_hdrcanon = (dkim_canon_t) c; } /* XXX -- eat this header? */ } return SMFIS_CONTINUE; } /* ** MLFI_EOH -- handler called when there are no more headers ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_eoh(SMFICTX *ctx) { char last; _Bool setidentity = FALSE; _Bool domainok; _Bool originok; _Bool didfrom = FALSE; #ifdef _FFR_RESIGN _Bool msgsigned = FALSE; #endif /* _FFR_RESIGN */ int c; DKIM_STAT status; sfsistat ms = SMFIS_CONTINUE; connctx cc; msgctx dfc; DKIM *lastdkim; char *p; #ifdef _FFR_SENDER_MACRO char *macrosender = NULL; #endif /* _FFR_SENDER_MACRO */ u_char *user; u_char *domain; #ifdef _FFR_VBR char *vbr_cert = NULL; char *vbr_type = NULL; #endif /* _FFR_VBR */ struct dkimf_config *conf; struct dkimf_dstring *addr; Header from = NULL; Header hdr; assert(ctx != NULL); cc = (connctx) dkimf_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); conf = cc->cctx_config; /* ** Determine the message ID for logging. */ dfc->mctx_jobid = (u_char *) dkimf_getsymval(ctx, "i"); if (dfc->mctx_jobid == NULL || dfc->mctx_jobid[0] == '\0') dfc->mctx_jobid = (u_char *) JOBIDUNKNOWN; /* find the Sender: or From: header */ addr = dkimf_dstring_new(BUFRSZ, 0); #ifdef _FFR_SENDER_MACRO if (conf->conf_sendermacro != NULL) { macrosender = dkimf_getsymval(ctx, conf->conf_sendermacro); if (macrosender != NULL) dkimf_dstring_copy(addr, macrosender); } #endif /* _FFR_SENDER_MACRO */ if (dkimf_dstring_len(addr) == 0) { for (c = 0; conf->conf_senderhdrs != NULL && conf->conf_senderhdrs[c] != NULL; c++) { if (strcasecmp("from", conf->conf_senderhdrs[c]) == 0) didfrom = TRUE; from = dkimf_findheader(dfc, conf->conf_senderhdrs[c], 0); if (from != NULL) break; } if (from == NULL && !didfrom) from = dkimf_findheader(dfc, "from", 0); } if (from != NULL) dkimf_dstring_copy(addr, from->hdr_val); if (dkimf_dstring_len(addr) == 0) { if (conf->conf_dolog) { syslog(LOG_INFO, "%s: can't determine message sender; accepting", dfc->mctx_jobid); } dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; dfc->mctx_status = DKIMF_STATUS_BADFORMAT; dkimf_dstring_free(addr); return SMFIS_CONTINUE; } status = dkim_mail_parse(dkimf_dstring_get(addr), &user, &domain); #ifdef _FFR_DEFAULT_SENDER if (conf->conf_defsender != NULL && (status != 0 || user == NULL || domain == NULL || user[0] == '\0' || domain[0] == '\0')) { strlcpy(addr, conf->conf_defsender, sizeof addr); status = dkim_mail_parse(addr, &user, &domain); } #endif /* _FFR_DEFAULT_SENDER */ if ((conf->conf_mode & DKIMF_MODE_SIGNER) != 0 && (status != 0 || user == NULL || domain == NULL || user[0] == '\0' || domain[0] == '\0')) { if (conf->conf_dolog) { #ifdef _FFR_SENDER_MACRO if (macrosender != NULL) { syslog(LOG_INFO, "%s: can't parse macro %s header value '%s'", dfc->mctx_jobid, conf->conf_sendermacro, macrosender); } else #endif /* _FFR_SENDER_MACRO */ if (from != NULL) { syslog(LOG_INFO, "%s: can't parse %s: header value '%s'", dfc->mctx_jobid, from->hdr_hdr, from->hdr_val); } #ifdef _FFR_DEFAULT_SENDER else if (conf->conf_defsender != NULL) { syslog(LOG_INFO, "%s: can't parse default sender value '%s'", dfc->mctx_jobid, conf->conf_defsender); } #endif /* _FFR_DEFAULT_SENDER */ } dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; dfc->mctx_status = DKIMF_STATUS_BADFORMAT; dkimf_dstring_free(addr); return SMFIS_CONTINUE; } if (domain != NULL) { strlcpy((char *) dfc->mctx_domain, (char *) domain, sizeof dfc->mctx_domain); dkimf_lowercase(dfc->mctx_domain); } /* if it's exempt, bail out */ if (conf->conf_exemptdb != NULL && dfc->mctx_domain[0] != '\0') { _Bool match = FALSE; int status; status = dkimf_db_get(conf->conf_exemptdb, dfc->mctx_domain, 0, NULL, 0, &match); if (status != 0) { if (dolog) { dkimf_db_error(conf->conf_exemptdb, (char *) dfc->mctx_domain); } dkimf_dstring_free(addr); return SMFIS_TEMPFAIL; } if (match) { if (conf->conf_logwhy) { syslog(LOG_INFO, "%s: domain '%s' exempted, accepting", dfc->mctx_jobid, dfc->mctx_domain); } dkimf_cleanup(ctx); dkimf_dstring_free(addr); return SMFIS_ACCEPT; } } /* apply BodyLengthDB if signing */ if (conf->conf_bldb != NULL && !dfc->mctx_bldbdone) { struct addrlist *a; for (a = dfc->mctx_rcptlist; a != NULL; a = a->a_next) { if (dkimf_checkbldb(conf->conf_bldb, a->a_addr, dfc->mctx_jobid)) { dfc->mctx_ltag = TRUE; dfc->mctx_laddr = a->a_addr; break; } } dfc->mctx_bldbdone = TRUE; } /* assume we're not signing */ dfc->mctx_signalg = DKIM_SIGN_UNKNOWN; domainok = FALSE; originok = FALSE; #ifdef _FFR_RESIGN msgsigned = (dkimf_findheader(dfc, DKIM_SIGNHEADER, 0) != NULL); /* check to see if it's a destination for which we resign */ if (conf->conf_resigndb != NULL) { bool match = FALSE; char *at; char *dot; struct addrlist *a; char resignkey[BUFRSZ + 1]; struct dkimf_db_data dbd; memset(resignkey, '\0', sizeof resignkey); dbd.dbdata_buffer = resignkey; dbd.dbdata_buflen = sizeof resignkey; dbd.dbdata_flags = 0; for (a = dfc->mctx_rcptlist; a != NULL; a = a->a_next) { /* full recipient address */ if (dkimf_db_get(conf->conf_resigndb, a->a_addr, 0, &dbd, 1, &match) != 0) { if (dolog) { dkimf_db_error(conf->conf_resigndb, a->a_addr); } continue; } if (match) { domainok = TRUE; originok = TRUE; dfc->mctx_resign = TRUE; break; } /* hostname only */ at = strchr(a->a_addr, '@'); if (at == NULL) continue; status = dkimf_db_get(conf->conf_resigndb, at + 1, 0, &dbd, 1, &match); if (status != 0) { if (dolog) { dkimf_db_error(conf->conf_resigndb, at + 1); } continue; } if (match) { domainok = TRUE; originok = TRUE; dfc->mctx_resign = TRUE; break; } /* iterate through ".domain" possibilities */ for (dot = strchr(at, '.'); dot != NULL; dot = strchr(dot + 1, '.')) { status = dkimf_db_get(conf->conf_resigndb, dot, 0, &dbd, 1, &match); if (status != 0) { if (dolog) { dkimf_db_error(conf->conf_resigndb, dot); } continue; } if (match) break; } if (match) { domainok = TRUE; originok = TRUE; dfc->mctx_resign = TRUE; break; } } if (match) { if (conf->conf_keytabledb == NULL || resignkey[0] == '\0') { status = dkimf_add_signrequest(dfc, NULL, NULL, NULL, (ssize_t) -1); if (status != 0) { if (dolog) { syslog(LOG_ERR, "%s: failed to add signature for default key", dfc->mctx_jobid); } dkimf_dstring_free(addr); return SMFIS_TEMPFAIL; } } else { status = dkimf_add_signrequest(dfc, conf->conf_keytabledb, resignkey, NULL, (ssize_t) -1); if (status != 0) { if (dolog) { syslog(LOG_ERR, "%s: failed to add signature for key '%s'", dfc->mctx_jobid, resignkey); } dkimf_dstring_free(addr); return SMFIS_TEMPFAIL; } } } } #endif /* _FFR_RESIGN */ /* see if it came in on an authorized MSA/MTA connection */ if (conf->conf_mtasdb != NULL) { char *mtaname; char *host; mtaname = dkimf_getsymval(ctx, "{daemon_name}"); host = dkimf_getsymval(ctx, "j"); status = 0; if (mtaname != NULL) { status = dkimf_db_get(conf->conf_mtasdb, mtaname, 0, NULL, 0, &originok); if (status != 0 && dolog) dkimf_db_error(conf->conf_mtasdb, mtaname); } if (!originok && status == 0 && conf->conf_logwhy) { syslog(LOG_INFO, "%s: no MTA name match (host=%s, MTA=%s)", dfc->mctx_jobid, host, mtaname == NULL ? "?" : mtaname); } } /* see if macro tests passed */ if (conf->conf_macrosdb != NULL) { _Bool done = FALSE; int n; char *val; char name[BUFRSZ + 1]; struct dkimf_db_data dbd; if (dfc->mctx_tmpstr == NULL) { dfc->mctx_tmpstr = dkimf_dstring_new(BUFRSZ, 0); if (dfc->mctx_tmpstr == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: dkimf_dstring_new() failed", dfc->mctx_jobid); } dkimf_cleanup(ctx); dkimf_dstring_free(addr); return SMFIS_TEMPFAIL; } } for (n = 0; !done && conf->conf_macros[n] != NULL; n++) { /* retrieve the macro */ snprintf(name, sizeof name, "{%s}", conf->conf_macros[n]); val = dkimf_getsymval(ctx, name); /* short-circuit if the macro's not set */ if (val == NULL) continue; memset(&dbd, '\0', sizeof dbd); dbd.dbdata_buffer = val; dbd.dbdata_buflen = strlen(val) + 1; dbd.dbdata_flags = 0; status = dkimf_db_get(conf->conf_macrosdb, conf->conf_macros[n], 0, &dbd, 1, &originok); if (status != 0 && dolog) dkimf_db_error(conf->conf_macrosdb, name); } if (!originok && conf->conf_logwhy) { syslog(LOG_INFO, "%s: no macros match", dfc->mctx_jobid); } } /* see if it came from an internal or authenticated source */ if (!originok) { _Bool internal; #ifdef POPAUTH _Bool popauth; #endif /* POPAUTH */ char *authtype; internal = dkimf_checkhost(conf->conf_internal, cc->cctx_host); internal = internal || dkimf_checkip(conf->conf_internal, (struct sockaddr *) &cc->cctx_ip); authtype = dkimf_getsymval(ctx, "{auth_type}"); #ifdef POPAUTH popauth = dkimf_checkpopauth(popdb, (struct sockaddr *) &cc->cctx_ip); #endif /* POPAUTH */ if ((authtype != NULL && authtype[0] != '\0') || internal) originok = TRUE; #ifdef POPAUTH if (popauth) originok = TRUE; #endif /* POPAUTH */ if (!originok && conf->conf_logwhy) { if (!internal) { char ipbuf[BUFRSZ]; dkimf_ipstring(ipbuf, sizeof ipbuf, &cc->cctx_ip); syslog(LOG_INFO, "%s: %s [%s] not internal", dfc->mctx_jobid, cc->cctx_host, ipbuf); } if (authtype == NULL || authtype[0] == '\0') { syslog(LOG_INFO, "%s: not authenticated", dfc->mctx_jobid); } #ifdef POPAUTH if (!popauth) { syslog(LOG_INFO, "%s: not POP authenticated", dfc->mctx_jobid); } #endif /* POPAUTH */ } } /* is it a domain we sign for? */ if (!domainok && conf->conf_domainsdb != NULL) { status = dkimf_db_get(conf->conf_domainsdb, dfc->mctx_domain, 0, NULL, 0, &domainok); if (!domainok) { /* check for "*" for back-compatibility */ status = dkimf_db_get(conf->conf_domainsdb, "*", 0, NULL, 0, &domainok); if (status != 0 && dolog) dkimf_db_error(conf->conf_domainsdb, "*"); } if (!domainok && conf->conf_logwhy) { syslog(LOG_INFO, "%s: no signing domain match for '%s'", dfc->mctx_jobid, dfc->mctx_domain); } if (conf->conf_subdomains && !domainok) { for (p = strchr((char *) dfc->mctx_domain, '.'); p != NULL && !domainok; p = strchr(p, '.')) { p++; if (*p == '\0') break; status = dkimf_db_get(conf->conf_domainsdb, p, 0, NULL, 0, &domainok); if (status != 0) { if (dolog) { dkimf_db_error(conf->conf_domainsdb, p); } continue; } if (domainok) { strlcpy((char *) dfc->mctx_domain, p, sizeof dfc->mctx_domain); break; } } if (domainok) setidentity = TRUE; } if (!domainok && conf->conf_logwhy) { syslog(LOG_INFO, "%s: no signing subdomain match for '%s'", dfc->mctx_jobid, dfc->mctx_domain); } } /* warn if the domain was OK but didn't come from a safe source */ if (domainok && !originok) { if (conf->conf_dolog && !dkimf_checkhost(conf->conf_exignore, cc->cctx_host) && !dkimf_checkip(conf->conf_exignore, (struct sockaddr *) &cc->cctx_ip)) { syslog(LOG_NOTICE, "%s: external host %s attempted to send as %s", dfc->mctx_jobid, cc->cctx_host, dfc->mctx_domain); } } /* still no key selected; check the signing table (if any) */ if (originok && dfc->mctx_srhead == NULL && (user != NULL && dfc->mctx_domain[0] != '\0') && #ifdef _FFR_LUA_ONLY_SIGNING !conf->conf_luasigning && #endif /* _FFR_LUA_ONLY_SIGNING */ conf->conf_keytabledb != NULL && conf->conf_signtabledb != NULL) { int found; char errkey[BUFRSZ + 1]; memset(errkey, '\0', sizeof errkey); found = dkimf_apply_signtable(dfc, conf->conf_keytabledb, conf->conf_signtabledb, user, dfc->mctx_domain, errkey, sizeof errkey, conf->conf_multisig); if (found < 0) { if (conf->conf_dolog) { switch (found) { case -1: syslog(LOG_ERR, "%s: error reading signing table", dfc->mctx_jobid); break; case -2: syslog(LOG_ERR, "%s: signing table references unknown key '%s'", dfc->mctx_jobid, errkey); break; case -3: syslog(LOG_ERR, "%s: error loading key '%s'", dfc->mctx_jobid, errkey); break; default: assert(0); } } dkimf_dstring_free(addr); return SMFIS_TEMPFAIL; } else if (found > 0) { domainok = TRUE; } if (!domainok && conf->conf_logwhy) { syslog(LOG_INFO, "%s: no signing table match for '%s@%s'", dfc->mctx_jobid, user, dfc->mctx_domain); } } /* don't need the sender field anymore */ dkimf_dstring_free(addr); /* set signing mode if the tests passed */ if (domainok && originok) { dfc->mctx_signalg = conf->conf_signalg; dfc->mctx_addheader = TRUE; } /* remember internal state */ dfc->mctx_internal = originok; #ifdef USE_LUA /* invoke the setup script if defined */ if (conf->conf_setupscript != NULL) { _Bool dofree = TRUE; struct dkimf_lua_script_result lres; memset(&lres, '\0', sizeof lres); dfc->mctx_mresult = SMFIS_CONTINUE; status = dkimf_lua_setup_hook(ctx, conf->conf_setupfunc, conf->conf_setupfuncsz, "setup script", &lres, NULL, NULL); if (status != 0) { if (conf->conf_dolog) { if (lres.lrs_error == NULL) { dofree = FALSE; switch (status) { case 2: lres.lrs_error = "processing error"; break; case 1: lres.lrs_error = "syntax error"; break; case -1: lres.lrs_error = "memory allocation error"; break; default: lres.lrs_error = "unknown error"; break; } } syslog(LOG_ERR, "%s: dkimf_lua_setup_hook() failed: %s", dfc->mctx_jobid, lres.lrs_error); } if (dofree) free(lres.lrs_error); return SMFIS_TEMPFAIL; } if (dfc->mctx_mresult != SMFIS_CONTINUE) return dfc->mctx_mresult; } #endif /* USE_LUA */ /* create a default signing request if there was a domain match */ if (domainok && originok && dfc->mctx_srhead == NULL) { status = dkimf_add_signrequest(dfc, NULL, NULL, NULL, (ssize_t) -1); if (status != 0) { if (dolog) { syslog(LOG_ERR, "%s: failed to add default signing request", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } } /* ** If we're not operating in the role matching the required operation, ** just accept the message and be done with it. */ /* signing requests with signing mode disabled */ if (dfc->mctx_srhead != NULL && (conf->conf_mode & DKIMF_MODE_SIGNER) == 0) return SMFIS_ACCEPT; /* verify request with verify mode disabled */ #ifdef _FFR_RESIGN if ((dfc->mctx_srhead == NULL || dfc->mctx_resign) && #else /* _FFR_RESIGN */ if (dfc->mctx_srhead == NULL && #endif /* _FFR_RESIGN */ (conf->conf_mode & DKIMF_MODE_VERIFIER) == 0) return SMFIS_ACCEPT; /* check for "DontSignMailTo" */ if (dfc->mctx_srhead != NULL && conf->conf_dontsigntodb != NULL) { _Bool found; int status; struct addrlist *a; a = dfc->mctx_rcptlist; while (a != NULL) { found = FALSE; status = dkimf_db_get(conf->conf_dontsigntodb, a->a_addr, 0, NULL, 0, &found); if (found) { if (conf->conf_dolog) { syslog(LOG_INFO, "%s: skipping signing of mail to '%s'", dfc->mctx_jobid, a->a_addr); } return SMFIS_ACCEPT; } else if (status != 0) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: dkimf_db_get() failed", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } a = a->a_next; } } #ifdef _FFR_RESIGN /* if we're not signing, or we are resigning, grab a verify handle */ if (dfc->mctx_srhead == NULL || dfc->mctx_resign) #else /* _FFR_RESIGN */ /* if we're not signing, grab a verify handle */ if (dfc->mctx_srhead == NULL) #endif /* _FFR_RESIGN */ { dfc->mctx_dkimv = dkim_verify(conf->conf_libopendkim, dfc->mctx_jobid, NULL, &status); if (dfc->mctx_dkimv == NULL && status != DKIM_STAT_OK) { return dkimf_libstatus(ctx, NULL, "dkim_verify()", status); } } #ifdef _FFR_RESIGN if (!msgsigned) { /* ** If the message was unsigned, we're just signing and not ** resigning. */ dfc->mctx_resign = FALSE; } #endif /* _FFR_RESIGN */ /* create all required signing handles */ if (dfc->mctx_srhead != NULL) { #ifdef _FFR_ATPS _Bool atps = FALSE; #endif /* _FFR_ATPS */ ssize_t signlen; u_char *sdomain; u_char *selector; struct signreq *sr; dkim_sigkey_t keydata; if (conf->conf_dolog && dfc->mctx_laddr != NULL) { syslog(LOG_INFO, "%s: BodyLengthDB matched %s, signing with l= requested", dfc->mctx_jobid, dfc->mctx_laddr); } #ifdef _FFR_ATPS if (conf->conf_atpsdb != NULL) { status = dkimf_db_get(conf->conf_atpsdb, dfc->mctx_domain, 0, NULL, 0, &atps); if (status != 0 && dolog) { dkimf_db_error(conf->conf_atpsdb, dfc->mctx_domain); } } #endif /* _FFR_ATPS */ for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next) { #ifdef _FFR_CONDITIONAL if (sr->srq_dkim != NULL) continue; #endif /* _FFR_CONDITIONAL */ if (sr->srq_signlen == (ssize_t) -1) signlen = conf->conf_signbytes; else signlen = sr->srq_signlen; if (sr->srq_keydata != NULL) { keydata = sr->srq_keydata; selector = sr->srq_selector; if (sr->srq_domain != NULL) sdomain = sr->srq_domain; else sdomain = dfc->mctx_domain; } else { sdomain = dfc->mctx_domain; keydata = (dkim_sigkey_t) conf->conf_seckey; selector = conf->conf_selector; } sr->srq_dkim = dkim_sign(conf->conf_libopendkim, dfc->mctx_jobid, NULL, keydata, selector, sdomain, dfc->mctx_hdrcanon, dfc->mctx_bodycanon, dfc->mctx_signalg, signlen, &status); if (sr->srq_dkim == NULL || status != DKIM_STAT_OK) { return dkimf_libstatus(ctx, NULL, "dkim_sign()", status); } if (conf->conf_reqreports) { status = dkim_add_xtag(sr->srq_dkim, DKIM_REPORTTAG, DKIM_REPORTTAGVAL); if (status != DKIM_STAT_OK && dolog) { syslog(LOG_ERR, "%s dkim_add_xtag() for \"%s\" failed", dfc->mctx_jobid, DKIM_REPORTTAG); } } #ifdef _FFR_ATPS if (atps) { status = dkim_add_xtag(sr->srq_dkim, DKIM_ATPSTAG, dfc->mctx_domain); if (status != DKIM_STAT_OK && dolog) { syslog(LOG_ERR, "%s dkim_add_xtag() for \"%s\" failed", dfc->mctx_jobid, DKIM_ATPSTAG); } status = dkim_add_xtag(sr->srq_dkim, DKIM_ATPSHTAG, conf->conf_atpshash); if (status != DKIM_STAT_OK && dolog) { syslog(LOG_ERR, "%s dkim_add_xtag() for \"%s\" failed", dfc->mctx_jobid, DKIM_ATPSHTAG); } } #endif /* _FFR_ATPS */ (void) dkim_set_user_context(sr->srq_dkim, ctx); if (sr->srq_signer != NULL) { (void) dkim_set_signer(sr->srq_dkim, sr->srq_signer); } #ifdef _FFR_RESIGN if (dfc->mctx_resign && dfc->mctx_dkimv != NULL) { status = dkim_resign(sr->srq_dkim, dfc->mctx_dkimv, FALSE); if (status != DKIM_STAT_OK) { return dkimf_libstatus(ctx, NULL, "dkim_resign()", status); } } #endif /* _FFR_RESIGN */ #ifdef _FFR_CONDITIONAL if (conf->conf_conditionaldb) { status = dkimf_check_conditional(dfc, conf, sr); if (status != DKIM_STAT_OK) { return dkimf_libstatus(ctx, NULL, "dkim_conditional()", status); } } #endif /* _FFR_CONDITIONAL */ } } /* if requested, verify RFC5322-required headers (RFC5322 3.6) */ if (conf->conf_reqhdrs) { char *msg = NULL; /* exactly one From: */ if (dkimf_findheader(dfc, "From", 0) == NULL || dkimf_findheader(dfc, "From", 1) != NULL) msg = "message does not have exactly one From field"; /* exactly one Date: */ if (dkimf_findheader(dfc, "Date", 0) == NULL || dkimf_findheader(dfc, "Date", 1) != NULL) msg = "message does not have exactly one Date field"; /* no more than one Reply-To: */ if (dkimf_findheader(dfc, "Reply-To", 1) != NULL) msg = "message has multiple Reply-To fields"; /* no more than one To: */ if (dkimf_findheader(dfc, "To", 1) != NULL) msg = "message has multiple To fields"; /* no more than one Cc: */ if (dkimf_findheader(dfc, "Cc", 1) != NULL) msg = "message has multiple Cc fields"; /* no more than one Bcc: */ if (dkimf_findheader(dfc, "Bcc", 1) != NULL) msg = "message has multiple Bcc fields"; /* no more than one Message-Id: */ if (dkimf_findheader(dfc, "Message-Id", 1) != NULL) msg = "message has multiple Message-Id fields"; /* no more than one In-Reply-To: */ if (dkimf_findheader(dfc, "In-Reply-To", 1) != NULL) msg = "message has multiple In-Reply-To fields"; /* no more than one References: */ if (dkimf_findheader(dfc, "References", 1) != NULL) msg = "message has multiple References fields"; /* no more than one Subject: */ if (dkimf_findheader(dfc, "Subject", 1) != NULL) msg = "message has multiple Subject fields"; if (msg != NULL) { if (conf->conf_dolog) { syslog(LOG_INFO, "%s: RFC5322 header requirement error: %s", dfc->mctx_jobid, msg); } if (dkimf_setreply(ctx, "550", "5.0.0", msg) != MI_SUCCESS && conf->conf_dolog) { syslog(LOG_NOTICE, "%s: smfi_setreply() failed", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_REJECT; } } #ifdef _FFR_IDENTITY_HEADER if (conf->conf_identityhdr != NULL) setidentity = TRUE; #endif /* _FFR_IDENTITY_HEADER */ if (dfc->mctx_srhead != NULL && setidentity) { u_char identity[MAXADDRESS + 1]; _Bool idset = FALSE; #ifdef _FFR_IDENTITY_HEADER if (conf->conf_identityhdr != NULL) { struct Header *hdr; u_char *iuser = NULL; u_char *idomain = NULL; hdr = dkimf_findheader(dfc, conf->conf_identityhdr, 0); if (hdr != NULL) { status = dkim_mail_parse(hdr->hdr_val, &iuser, &idomain); if (status == 0 && idomain != NULL) { snprintf((char *) identity, sizeof identity, "%s@%s", iuser == NULL ? "" : (char *) iuser, idomain); idset = TRUE; } } if (!idset && conf->conf_dolog) { syslog(LOG_INFO, "%s: cannot find identity header %s", dfc->mctx_jobid, conf->conf_identityhdr); } } #endif /* _FFR_IDENTITY_HEADER */ if (!idset) { snprintf((char *) identity, sizeof identity, "@%s", dfc->mctx_domain); } if (dfc->mctx_srhead != NULL) { struct signreq *sr; for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next) { if (dkim_get_signer(sr->srq_dkim) == NULL) { dkim_set_signer(sr->srq_dkim, identity); } } } } if (dfc->mctx_ltag && dfc->mctx_srhead != NULL) { struct signreq *sr; for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next) dkim_setpartial(sr->srq_dkim, TRUE); } #ifdef _FFR_VBR /* establish a VBR handle */ dfc->mctx_vbr = vbr_init(NULL, NULL, NULL); if (dfc->mctx_vbr == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: can't create VBR context", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } # ifdef USE_UNBOUND dkimf_vbr_unbound_setup(dfc->mctx_vbr); # endif /* USE_UNBOUND */ if (conf->conf_vbr_trustedonly) vbr_options(dfc->mctx_vbr, VBR_OPT_TRUSTEDONLY); /* store the trusted certifiers */ if (conf->conf_vbr_trusted != NULL) vbr_trustedcerts(dfc->mctx_vbr, conf->conf_vbr_trusted); if (vbr_dns_init(dfc->mctx_vbr) != 0) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: can't initialize VBR resolver", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } if (conf->conf_nslist != NULL) { status = vbr_dns_nslist(dfc->mctx_vbr, conf->conf_nslist); if (status != VBR_STAT_OK) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: can't set VBR resolver list", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } if (conf->conf_trustanchorpath != NULL) { if (access(conf->conf_trustanchorpath, R_OK) != 0) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s: access(): %s", dfc->mctx_jobid, conf->conf_trustanchorpath, strerror(errno)); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } status = vbr_dns_trustanchor(dfc->mctx_vbr, conf->conf_trustanchorpath); if (status != DKIM_STAT_OK) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: can't set VBR trust anchor from %s", dfc->mctx_jobid, conf->conf_trustanchorpath); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } if (conf->conf_resolverconfig != NULL) { status = vbr_dns_config(dfc->mctx_vbr, conf->conf_resolverconfig); if (status != DKIM_STAT_OK) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: can't set VBR resolver configuration", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } if (dfc->mctx_srhead != NULL) { Header newhdr; char header[DKIM_MAXHEADER + 1]; /* set the sending domain */ vbr_setdomain(dfc->mctx_vbr, dfc->mctx_domain); /* VBR-Type; get value from headers or use default */ hdr = dkimf_findheader(dfc, VBRTYPEHEADER, 0); if (hdr != NULL) { dfc->mctx_vbrpurge = TRUE; vbr_type = hdr->hdr_val; } else { vbr_type = conf->conf_vbr_deftype; } /* X-VBR-Certifiers; get value from headers or use default */ hdr = dkimf_findheader(dfc, VBRCERTHEADER, 0); if (hdr != NULL) { dfc->mctx_vbrpurge = TRUE; vbr_cert = hdr->hdr_val; } else { vbr_cert = conf->conf_vbr_defcert; } /* set message type and certifiers, and generate a header */ if (vbr_type != NULL && vbr_cert != NULL) { memset(header, '\0', sizeof header); /* set the VBR transaction type */ (void) vbr_settype(dfc->mctx_vbr, (u_char *) vbr_type); /* set the VBR certifier list */ (void) vbr_setcert(dfc->mctx_vbr, (u_char *) vbr_cert); status = vbr_getheader(dfc->mctx_vbr, header, sizeof header); if (status != VBR_STAT_OK) { const char *err; err = vbr_geterror(dfc->mctx_vbr); syslog(LOG_ERR, "%s: can't create VBR-Info header field%s%s", dfc->mctx_jobid, err == NULL ? "" : ": ", err == NULL ? "" : err); } else { /* store it for addition in mlfi_eom() */ dfc->mctx_vbrinfo = strdup(header); if (dfc->mctx_vbrinfo == NULL) { syslog(LOG_ERR, "%s: strdup(): %s", dfc->mctx_jobid, strerror(errno)); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } /* add it to header set so it gets signed */ newhdr = (Header) malloc(sizeof(struct Header)); if (newhdr == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "malloc(): %s", strerror(errno)); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } (void) memset(newhdr, '\0', sizeof(struct Header)); newhdr->hdr_hdr = strdup(VBR_INFOHEADER); newhdr->hdr_val = strdup(header); if (newhdr->hdr_hdr == NULL || newhdr->hdr_val == NULL) { syslog(LOG_ERR, "%s: strdup(): %s", dfc->mctx_jobid, strerror(errno)); TRYFREE(newhdr->hdr_hdr); dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } newhdr->hdr_next = NULL; newhdr->hdr_prev = dfc->mctx_hqtail; if (dfc->mctx_hqhead == NULL) dfc->mctx_hqhead = newhdr; if (dfc->mctx_hqtail != NULL) dfc->mctx_hqtail->hdr_next = newhdr; dfc->mctx_hqtail = newhdr; } } } #endif /* _FFR_VBR */ /* run the headers */ for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { if (dfc->mctx_tmpstr == NULL) { dfc->mctx_tmpstr = dkimf_dstring_new(BUFRSZ, 0); if (dfc->mctx_tmpstr == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: dkimf_dstring_new() failed", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } } else { dkimf_dstring_blank(dfc->mctx_tmpstr); } /* ** Skip headers we know we're going to delete before ** signing here (e.g. identity header when set to remove). */ /* ** XXX -- may need to skip some/all Authentication-Results ** header fields here, especially in the re-signing case */ #ifdef _FFR_IDENTITY_HEADER if (conf->conf_identityhdr != NULL && conf->conf_rmidentityhdr && dfc->mctx_srhead != NULL && strcasecmp(conf->conf_identityhdr, hdr->hdr_hdr) == 0) continue; #endif /* _FFR_IDENTITY_HEADER */ dkimf_dstring_copy(dfc->mctx_tmpstr, (u_char *) hdr->hdr_hdr); dkimf_dstring_cat1(dfc->mctx_tmpstr, ':'); if (!cc->cctx_noleadspc) dkimf_dstring_cat1(dfc->mctx_tmpstr, ' '); last = '\0'; /* do milter-ized continuation conversion */ for (p = hdr->hdr_val; *p != '\0'; p++) { if (*p == '\n' && last != '\r') dkimf_dstring_cat1(dfc->mctx_tmpstr, '\r'); dkimf_dstring_cat1(dfc->mctx_tmpstr, *p); last = *p; } #ifdef _FFR_REPUTATION /* check for spam flag */ if (conf->conf_repspamcheck != NULL && regexec(&conf->conf_repspamre, dkimf_dstring_get(dfc->mctx_tmpstr), 0, NULL, 0) == 0) dfc->mctx_spam = TRUE; #endif /* _FFR_REPUTATION */ if (dfc->mctx_srhead != NULL) { DKIM *dkim; status = dkimf_msr_header(dfc->mctx_srhead, &dkim, dkimf_dstring_get(dfc->mctx_tmpstr), dkimf_dstring_len(dfc->mctx_tmpstr)); if (status != DKIM_STAT_OK) { ms = dkimf_libstatus(ctx, dkim, "dkim_header()", status); break; } } if (dfc->mctx_dkimv != NULL) { status = dkim_header(dfc->mctx_dkimv, (u_char *) dkimf_dstring_get(dfc->mctx_tmpstr), dkimf_dstring_len(dfc->mctx_tmpstr)); if (status != DKIM_STAT_OK) { ms = dkimf_libstatus(ctx, dfc->mctx_dkimv, "dkim_header()", status); } } } /* return any error status from earlier */ if (ms != SMFIS_CONTINUE) return ms; /* signal end of headers to libopendkim */ lastdkim = NULL; status = DKIM_STAT_OK; #ifdef _FFR_RESIGN if (dfc->mctx_srhead != NULL && !dfc->mctx_resign) #else /* _FFR_RESIGN */ if (dfc->mctx_srhead != NULL) #endif /* _FFR_RESIGN */ status = dkimf_msr_eoh(dfc->mctx_srhead, &lastdkim); if (status == DKIM_STAT_OK && dfc->mctx_dkimv != NULL) { (void) dkim_set_user_context(dfc->mctx_dkimv, ctx); lastdkim = dfc->mctx_dkimv; status = dkim_eoh(dfc->mctx_dkimv); } #ifdef USE_LUA if (conf->conf_screenscript != NULL) { _Bool dofree = TRUE; struct dkimf_lua_script_result lres; memset(&lres, '\0', sizeof lres); status = dkimf_lua_screen_hook(ctx, conf->conf_screenfunc, conf->conf_screenfuncsz, "screen script", &lres, NULL, NULL); if (status != 0) { if (conf->conf_dolog) { if (lres.lrs_error == NULL) { dofree = FALSE; switch (status) { case 2: lres.lrs_error = "processing error"; break; case 1: lres.lrs_error = "syntax error"; break; case -1: lres.lrs_error = "memory allocation error"; break; default: lres.lrs_error = "unknown error"; break; } } syslog(LOG_ERR, "%s: dkimf_lua_screen_hook() failed: %s", dfc->mctx_jobid, lres.lrs_error); } if (dofree) free(lres.lrs_error); return SMFIS_TEMPFAIL; } } #endif /* USE_LUA */ switch (status) { case DKIM_STAT_REVOKED: dfc->mctx_status = DKIMF_STATUS_REVOKED; dfc->mctx_addheader = TRUE; return SMFIS_CONTINUE; case DKIM_STAT_BADSIG: dfc->mctx_status = DKIMF_STATUS_BAD; dfc->mctx_addheader = TRUE; return SMFIS_CONTINUE; case DKIM_STAT_NOSIG: dfc->mctx_status = DKIMF_STATUS_NOSIGNATURE; if (conf->conf_alwaysaddar) dfc->mctx_addheader = TRUE; return SMFIS_CONTINUE; case DKIM_STAT_NOKEY: dfc->mctx_status = DKIMF_STATUS_NOKEY; dfc->mctx_addheader = TRUE; return SMFIS_CONTINUE; case DKIM_STAT_SYNTAX: dfc->mctx_status = DKIMF_STATUS_BADFORMAT; dfc->mctx_addheader = TRUE; dfc->mctx_headeronly = TRUE; return SMFIS_CONTINUE; /* XXX -- other codes? */ case DKIM_STAT_OK: return SMFIS_CONTINUE; default: return dkimf_libstatus(ctx, lastdkim, "dkim_eoh()", status); } } /* ** MLFI_BODY -- handler for an arbitrary body block ** ** Parameters: ** ctx -- milter context ** bodyp -- body block ** bodylen -- amount of data available at bodyp ** ** Return value: ** An SMFIS_* constant. ** ** Description: ** This function reads the body chunks passed by the MTA and ** stores them for later wrapping, if needed. */ sfsistat mlfi_body(SMFICTX *ctx, u_char *bodyp, size_t bodylen) { int status; DKIM *last; msgctx dfc; connctx cc; assert(ctx != NULL); assert(bodyp != NULL); cc = (connctx) dkimf_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); /* ** No need to do anything if the body was empty. */ if (bodylen == 0) return SMFIS_CONTINUE; #ifdef _FFR_REPUTATION # ifdef USE_GNUTLS (void) gnutls_hash(dfc->mctx_hash, bodyp, bodylen); # else /* USE_GNUTLS */ SHA1_Update(&dfc->mctx_hash, bodyp, bodylen); # endif /* USE_GNUTLS */ #endif /* _FFR_REPUTATION */ /* ** Tell the filter to skip it if we don't care about the body. */ if (dfc->mctx_headeronly) { #ifdef SMFIS_SKIP if (cc->cctx_milterv2) return SMFIS_SKIP; else return SMFIS_CONTINUE; #else /* SMFIS_SKIP */ return SMFIS_CONTINUE; #endif /* SMFIS_SKIP */ } last = NULL; status = DKIM_STAT_OK; #ifdef _FFR_RESIGN if (dfc->mctx_srhead != NULL && (!dfc->mctx_resign || dfc->mctx_dkimv == NULL)) #else /* _FFR_RESIGN */ if (dfc->mctx_srhead != NULL) #endif /* _FFR_RESIGN */ { status = dkimf_msr_body(dfc->mctx_srhead, &last, bodyp, bodylen); } if (status == DKIM_STAT_OK && dfc->mctx_dkimv != NULL) { last = dfc->mctx_dkimv; status = dkim_body(dfc->mctx_dkimv, bodyp, bodylen); } if (status != DKIM_STAT_OK) return dkimf_libstatus(ctx, last, "dkim_body()", status); #ifdef SMFIS_SKIP /* skip the body if neither signing mode nor verify mode need it */ if (cc->cctx_milterv2 && (dfc->mctx_srhead == NULL || dkimf_msr_minbody(dfc->mctx_srhead) == 0) && (dfc->mctx_dkimv == NULL || dkim_minbody(dfc->mctx_dkimv) == 0)) return SMFIS_SKIP; #endif /* SMFIS_SKIP */ return SMFIS_CONTINUE; } /* ** MLFI_EOM -- handler called at the end of the message; we can now decide ** based on the configuration if and how to add the text ** to this message, then release resources ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_eom(SMFICTX *ctx) { _Bool testkey = FALSE; _Bool authorsig; int status = DKIM_STAT_OK; int c; sfsistat ret; connctx cc; msgctx dfc; DKIM *lastdkim = NULL; char *authservid; char *hostname; struct dkimf_config *conf; DKIM_SIGINFO *sig = NULL; Header hdr; unsigned char header[DKIM_MAXHEADER + 1]; assert(ctx != NULL); cc = (connctx) dkimf_getpriv(ctx); assert(cc != NULL); dfc = cc->cctx_msg; assert(dfc != NULL); conf = cc->cctx_config; dfc->mctx_eom = TRUE; /* ** If necessary, try again to get the job ID in case it came down ** later than expected (e.g. postfix). */ if (strcmp((char *) dfc->mctx_jobid, JOBIDUNKNOWN) == 0) { dfc->mctx_jobid = (u_char *) dkimf_getsymval(ctx, "i"); if (dfc->mctx_jobid == NULL || dfc->mctx_jobid[0] == '\0') { if (no_i_whine && conf->conf_dolog) { syslog(LOG_WARNING, "WARNING: symbol 'i' not available"); no_i_whine = FALSE; } dfc->mctx_jobid = (u_char *) JOBIDUNKNOWN; } } /* get hostname; used in the X header and in new MIME boundaries */ hostname = dkimf_getsymval(ctx, "j"); if (hostname == NULL) hostname = HOSTUNKNOWN; /* select authserv-id to use when generating result headers */ authservid = conf->conf_authservid; if (authservid == NULL) authservid = hostname; /* if this was totally malformed, add a header field and stop */ if (dfc->mctx_headeronly) { /* allow for override */ if (conf->conf_passmalformed) return SMFIS_ACCEPT; const char *ar; switch (dfc->mctx_status) { case DKIMF_STATUS_BAD: ar = "fail"; break; case DKIMF_STATUS_NOKEY: case DKIMF_STATUS_BADFORMAT: ar = "permerror"; break; case DKIMF_STATUS_NOSIGNATURE: ar = "none"; break; case DKIMF_STATUS_GOOD: case DKIMF_STATUS_REVOKED: case DKIMF_STATUS_PARTIAL: case DKIMF_STATUS_VERIFYERR: case DKIMF_STATUS_UNKNOWN: default: assert(0); /* NOTREACHED */ } snprintf(header, sizeof header, "%s; dkim=%s (%s)", authservid, ar, dkimf_lookup_inttostr(dfc->mctx_status, dkimf_statusstrings)); if (dkimf_insheader(ctx, 1, AUTHRESULTSHDR, (char *) header) == MI_FAILURE) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header add failed", dfc->mctx_jobid, AUTHRESULTSHDR); } return SMFIS_TEMPFAIL; } return SMFIS_ACCEPT; } /* remove old signatures when signing */ if (conf->conf_remsigs && dfc->mctx_srhead != NULL) { for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { if (strcasecmp(hdr->hdr_hdr, DKIM_SIGNHEADER) == 0) { if (dkimf_chgheader(ctx, hdr->hdr_hdr, 0, NULL) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_WARNING, "failed to remove %s: header", hdr->hdr_hdr); } } } } } #ifdef _FFR_IDENTITY_HEADER /* remove identity header if such was requested when signing */ if (conf->conf_rmidentityhdr && conf->conf_identityhdr != NULL && dfc->mctx_srhead != NULL) { struct Header *hdr; hdr = dkimf_findheader(dfc, conf->conf_identityhdr, 0); if (hdr != NULL) { if (dkimf_chgheader(ctx, conf->conf_identityhdr, 0, NULL) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_WARNING, "failed to remove %s: header", conf->conf_identityhdr); } } } } #endif /* _FFR_IDENTITY_HEADER */ /* log something if the message was multiply signed */ if (dfc->mctx_dkimv != NULL && conf->conf_dolog) { int nsigs; DKIM_SIGINFO **sigs; lastdkim = dfc->mctx_dkimv; status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status == DKIM_STAT_OK && nsigs > 1) { u_char *d; if (dfc->mctx_tmpstr == NULL) { dfc->mctx_tmpstr = dkimf_dstring_new(BUFRSZ, 0); if (dfc->mctx_tmpstr == NULL) { syslog(LOG_WARNING, "%s: dkimf_dstring_new() failed", dfc->mctx_jobid); return SMFIS_TEMPFAIL; } } else { dkimf_dstring_blank(dfc->mctx_tmpstr); } dkimf_dstring_cat(dfc->mctx_tmpstr, dfc->mctx_jobid); dkimf_dstring_cat(dfc->mctx_tmpstr, (u_char *) ": message has signatures from "); for (c = 0; c < nsigs; c++) { if (c != 0) { dkimf_dstring_cat(dfc->mctx_tmpstr, (u_char *) ", "); } d = dkim_sig_getdomain(sigs[c]); if (d == NULL) d = (u_char *) NULLDOMAIN; dkimf_dstring_cat(dfc->mctx_tmpstr, d); } syslog(LOG_INFO, "%s", dkimf_dstring_get(dfc->mctx_tmpstr)); } } /* ** Remove all Authentication-Results: headers as per configuration ** options when verifying. */ if (dfc->mctx_dkimv != NULL && !conf->conf_keepar) { struct authres *ares; ares = (struct authres *) malloc(sizeof(struct authres)); if (ares == NULL) { syslog(LOG_WARNING, "%s: malloc(): %s", dfc->mctx_jobid, strerror(errno)); return SMFIS_TEMPFAIL; } c = 0; for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { memset(ares, '\0', sizeof(struct authres)); if (strcasecmp(hdr->hdr_hdr, AUTHRESULTSHDR) == 0) { _Bool dkimres = FALSE; _Bool hostmatch = FALSE; int arstat; char *slash; /* remember index */ c++; /* parse the header */ arstat = ares_parse((u_char *) hdr->hdr_val, ares); if (arstat == -1) { if (conf->conf_dolog) { syslog(LOG_WARNING, "%s: failed to parse %s: header field", dfc->mctx_jobid, hdr->hdr_hdr); } continue; } /* method match? */ if (conf->conf_remarall) { dkimres = TRUE; } else { int d; for (d = 0; d < ares->ares_count; d++) { if (ares->ares_result[d].result_method == ARES_METHOD_DKIM) dkimres = TRUE; } } /* hostname match? */ slash = strchr((char *) ares->ares_host, '/'); if (slash != NULL) *slash = '\0'; if (conf->conf_remardb != NULL) { status = dkimf_db_get(conf->conf_remardb, ares->ares_host, 0, NULL, 0, &hostmatch); if (status != 0 && dolog) { dkimf_db_error(conf->conf_remardb, (char *) ares->ares_host); } } else { if (strcasecmp(authservid, (char *) ares->ares_host) == 0) hostmatch = TRUE; } /* delete if we found both */ if (dkimres && hostmatch) { if (dkimf_chgheader(ctx, hdr->hdr_hdr, c, NULL) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_WARNING, "failed to remove %s: header", hdr->hdr_hdr); } } } } } free(ares); } /* complete verification if started */ if (dfc->mctx_dkimv != NULL) { /* ** Signal end-of-message to DKIM */ status = dkim_eom(dfc->mctx_dkimv, &testkey); lastdkim = dfc->mctx_dkimv; if (conf->conf_logresults && conf->conf_dolog) { int c; int nsigs; DKIM_STAT lstatus; DKIM_SIGINFO **sigs; if (dfc->mctx_tmpstr == NULL) { dfc->mctx_tmpstr = dkimf_dstring_new(BUFRSZ, 0); if (dfc->mctx_tmpstr == NULL) { syslog(LOG_WARNING, "%s: dkimf_dstring_new() failed", dfc->mctx_jobid); return SMFIS_TEMPFAIL; } } else { dkimf_dstring_blank(dfc->mctx_tmpstr); } lstatus = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (lstatus == DKIM_STAT_OK) { DKIM_SIGERROR err; size_t len; const char *domain; const char *selector; const char *errstr; char substr[BUFRSZ]; for (c = 0; c < nsigs; c++) { domain = dkim_sig_getdomain(sigs[c]); selector = dkim_sig_getselector(sigs[c]); err = dkim_sig_geterror(sigs[c]); errstr = dkim_sig_geterrorstr(err); memset(substr, '\0', sizeof substr); len = sizeof substr; lstatus = dkim_get_sigsubstring(dfc->mctx_dkimv, sigs[c], substr, &len); if (lstatus == DKIM_STAT_OK && domain != NULL && selector != NULL && errstr != NULL) { if (dkimf_dstring_len(dfc->mctx_tmpstr) > 0) { dkimf_dstring_catn(dfc->mctx_tmpstr, "; ", 2); } dkimf_dstring_printf(dfc->mctx_tmpstr, "signature=%s domain=%s selector=%s result=\"%s\"", substr, domain, selector, errstr); } } if (dkimf_dstring_len(dfc->mctx_tmpstr) > 0) { syslog(LOG_INFO, "%s: %s", dfc->mctx_jobid, dkimf_dstring_get(dfc->mctx_tmpstr)); } } } switch (status) { case DKIM_STAT_OK: if (dkimf_findheader(dfc, DKIM_SIGNHEADER, 0) != NULL) { if (conf->conf_dolog_success) { syslog(LOG_INFO, "%s: DKIM verification successful", dfc->mctx_jobid); } dfc->mctx_addheader = TRUE; dfc->mctx_status = DKIMF_STATUS_GOOD; } break; case DKIM_STAT_CANTVRFY: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKIMF_STATUS_VERIFYERR; break; case DKIM_STAT_BADSIG: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKIMF_STATUS_BAD; break; case DKIM_STAT_NOSIG: if (conf->conf_alwaysaddar) { dfc->mctx_addheader = TRUE; dfc->mctx_status = DKIMF_STATUS_NOSIGNATURE; } break; case DKIM_STAT_NOKEY: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKIMF_STATUS_NOKEY; break; case DKIM_STAT_REVOKED: dfc->mctx_addheader = TRUE; dfc->mctx_status = DKIMF_STATUS_REVOKED; break; default: if (conf->conf_dolog) { lastdkim = dfc->mctx_dkimv; sig = dkim_getsignature(dfc->mctx_dkimv); dkimf_log_ssl_errors(lastdkim, sig, (char *) dfc->mctx_jobid); } status = dkimf_libstatus(ctx, dfc->mctx_dkimv, "dkim_eom()", status); #ifdef SMFIF_QUARANTINE if (dfc->mctx_capture) { if (dkimf_quarantine(ctx, "capture requested") != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: smfi_quarantine() failed", dfc->mctx_jobid); } } status = SMFIS_ACCEPT; } #endif /* ! SMFIF_QUARANTINE */ break; } authorsig = dkimf_authorsigok(dfc); if (conf->conf_diagdir != NULL && dfc->mctx_status == DKIMF_STATUS_BAD) { int nhdrs; dkim_canon_t canon; u_char *ohdrs[MAXHDRCNT]; nhdrs = MAXHDRCNT; memset(ohdrs, '\0', sizeof ohdrs); sig = dkim_getsignature(dfc->mctx_dkimv); (void) dkim_sig_getcanons(sig, &canon, NULL); status = dkim_ohdrs(dfc->mctx_dkimv, sig, ohdrs, &nhdrs); if (status == DKIM_STAT_OK && nhdrs > 0) { FILE *f; char dpath[MAXPATHLEN + 1]; snprintf(dpath, sizeof dpath, "%s/%s", conf->conf_diagdir, dfc->mctx_jobid); f = fopen(dpath, "w"); if (f == NULL) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s: fopen(): %s", dfc->mctx_jobid, dpath, strerror(errno)); } } else { int c; #ifdef _FFR_DIFFHEADERS int ndiffs; struct dkim_hdrdiff *diffs; #endif /* _FFR_DIFFHEADERS */ struct Header *hdr; fprintf(f, "z tag headers:\n\n"); for (c = 0; c < nhdrs; c++) fprintf(f, "%s\n", ohdrs[c]); fprintf(f, "--------------------\n\n"); fprintf(f, "Received headers:\n\n"); for (hdr = dfc->mctx_hqhead; hdr != NULL; hdr = hdr->hdr_next) { fprintf(f, "%s:%s%s\n", hdr->hdr_hdr, cc->cctx_noleadspc ? "" : " ", hdr->hdr_val); } #ifdef _FFR_DIFFHEADERS /* XXX -- make the "5" configurable */ status = dkim_diffheaders(dfc->mctx_dkimv, canon, 5, (char **) ohdrs, nhdrs, &diffs, &ndiffs); if (status == DKIM_STAT_OK && diffs != NULL && ndiffs > 0) { fprintf(f, "--------------------\n\n"); fprintf(f, "Munging detected:\n\n"); for (c = 0; c < ndiffs; c++) { fprintf(f, "-%s\n+%s\n\n", diffs[c].hd_old, diffs[c].hd_new); } if (ndiffs > 0) free(diffs); } #endif /* _FFR_DIFFHEADERS */ fclose(f); } } } if (dfc->mctx_status == DKIMF_STATUS_GOOD) { if (conf->conf_sigmin > 0) { ssize_t canonlen; ssize_t bodylen; sig = dkim_getsignature(dfc->mctx_dkimv); (void) dkim_sig_getcanonlen(dfc->mctx_dkimv, sig, &bodylen, &canonlen, NULL); if (conf->conf_sigmintype == SIGMIN_PERCENT) { size_t signpct; signpct = (100 * canonlen) / bodylen; if (signpct < conf->conf_sigmin) dfc->mctx_status = DKIMF_STATUS_PARTIAL; } else if (conf->conf_sigmintype == SIGMIN_MAXADD) { if (canonlen + conf->conf_sigmin < bodylen) dfc->mctx_status = DKIMF_STATUS_PARTIAL; } else { size_t required; required = MIN(conf->conf_sigmin, bodylen); if (canonlen < required) dfc->mctx_status = DKIMF_STATUS_PARTIAL; } } } #ifdef USE_UNBOUND sig = dkim_getsignature(dfc->mctx_dkimv); if (sig != NULL) dfc->mctx_dnssec_key = dkim_sig_getdnssec(sig); #endif /* USE_UNBOUND */ #ifdef _FFR_ATPS if (dfc->mctx_status != DKIMF_STATUS_UNKNOWN && !authorsig) { int nsigs; dkim_atps_t atps = DKIM_ATPS_UNKNOWN; DKIM_SIGINFO **sigs; status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status == DKIM_STAT_OK) { for (c = 0; c < nsigs && atps != DKIM_ATPS_FOUND; c++) { if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0 && dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH && strcasecmp(dkim_sig_getdomain(sigs[c]), dfc->mctx_domain) != 0) { status = dkim_atps_check(dfc->mctx_dkimv, sigs[c], NULL, &atps); if (status != DKIM_STAT_OK) break; } } dfc->mctx_atps = atps; } } #endif /* _FFR_ATPS */ #ifdef _FFR_STATS if (conf->conf_statspath != NULL && dfc->mctx_dkimv != NULL) { # ifdef USE_LUA # ifdef _FFR_STATSEXT if (conf->conf_statsscript != NULL) { _Bool dofree = TRUE; struct dkimf_lua_script_result lres; memset(&lres, '\0', sizeof lres); status = dkimf_lua_stats_hook(ctx, conf->conf_statsfunc, conf->conf_statsfuncsz, "stats script", &lres, NULL, NULL); if (status != 0) { if (conf->conf_dolog) { if (lres.lrs_error == NULL) { dofree = FALSE; switch (status) { case 2: lres.lrs_error = "processing error"; break; case 1: lres.lrs_error = "syntax error"; break; case -1: lres.lrs_error = "memory allocation error"; break; default: lres.lrs_error = "unknown error"; break; } } syslog(LOG_ERR, "%s: dkimf_lua_stats_hook() failed: %s", dfc->mctx_jobid, lres.lrs_error); } if (dofree) free(lres.lrs_error); return SMFIS_TEMPFAIL; } } # endif /* _FFR_STATSEXT */ # endif /* USE_LUA */ if (dkimf_stats_record(conf->conf_statspath, dfc->mctx_jobid, conf->conf_reporthost, conf->conf_reportprefix, dfc->mctx_hqhead, dfc->mctx_dkimv, # ifdef _FFR_STATSEXT dfc->mctx_statsext, # endif /* _FFR_STATSEXT */ # ifdef _FFR_ATPS dfc->mctx_atps, # else /* _FFR_ATPS */ -1, # endif /* _FFR_ATPS */ # ifdef _FFR_REPUTATION dfc->mctx_spam, # else /* _FFR_REPUTATION */ -1, # endif /* _FFR_REPUTATION */ (struct sockaddr *) &cc->cctx_ip) != 0) { if (dolog) { syslog(LOG_WARNING, "statistics recording failed"); } } } #endif /* _FFR_STATS */ #ifdef _FFR_REPRRD if (dfc->mctx_dkimv != NULL && conf->conf_reprrd != NULL) { DKIM_SIGINFO **sigs; int nsigs; status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status == DKIM_STAT_OK) { int c; int ret; const char *cd; const char *domain = NULL; for (c = 0; c < nsigs && domain == NULL; c++) { if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) == 0 || (dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_TESTKEY) != 0 || dkim_sig_getbh(sigs[c]) != DKIM_SIGBH_MATCH) continue; cd = dkim_sig_getdomain(sigs[c]); ret = 0; status = reprrd_query(conf->conf_reprrd, cd, REPRRD_TYPE_MESSAGES, &ret, NULL, 0); if (status == 0 && ret == 0) { status = reprrd_query(conf->conf_reprrd, cd, REPRRD_TYPE_SPAM, &ret, NULL, 0); } if (status == 0 && ret == 0) { status = reprrd_query(conf->conf_reprrd, cd, REPRRD_TYPE_LIMIT, &ret, NULL, 0); } if (status == 0) { if (ret == 1) { domain = cd; break; } else if (conf->conf_dolog) { syslog(LOG_NOTICE, "%s: allowed by reputation of %s", dfc->mctx_jobid, cd); } } else if (status != REPRRD_STAT_NODATA) { if (conf->conf_dolog) { syslog(LOG_NOTICE, "%s: reputation query for \"%s\" failed (%d)", dfc->mctx_jobid, cd, status); } return dkimf_miltercode(ctx, conf->conf_handling.hndl_reperr, NULL); } else if (conf->conf_dolog) { syslog(LOG_NOTICE, "%s: no reputation data available for \"%s\"", dfc->mctx_jobid, cd); } } if (domain == NULL) { cd = "unsigned"; status = reprrd_query(conf->conf_reprrd, cd, REPRRD_TYPE_MESSAGES, &ret, NULL, 0); if (status == 0 && ret == 0) { status = reprrd_query(conf->conf_reprrd, cd, REPRRD_TYPE_SPAM, &ret, NULL, 0); } if (status == 0 && ret == 0) { status = reprrd_query(conf->conf_reprrd, cd, REPRRD_TYPE_LIMIT, &ret, NULL, 0); } if (status == 1) { domain = "NULL domain"; } else if (status == -1) { if (conf->conf_dolog) { syslog(LOG_NOTICE, "%s: reputation query for NULL domain failed (%d)", dfc->mctx_jobid, status); } return dkimf_miltercode(ctx, conf->conf_handling.hndl_reperr, NULL); } } if (domain != NULL) { if (dolog) { syslog(LOG_NOTICE, "%s: %sblocked by reputation of %s", dfc->mctx_jobid, conf->conf_reptest ? "would be " : "", domain); } if (!conf->conf_reptest) { if (dkimf_setreply(ctx, REPDENYSMTP, REPDENYESC, REPDENYTXT) != MI_SUCCESS && conf->conf_dolog) { syslog(LOG_NOTICE, "%s: smfi_setreply() failed", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } } } #endif /* _FFR_REPRRD */ #ifdef _FFR_REPUTATION if (dfc->mctx_dkimv != NULL && conf->conf_rep != NULL && !dfc->mctx_internal) { float ratio; unsigned long count; unsigned long limit; unsigned long spam; DKIM_SIGINFO **sigs; int nsigs; status = dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs); if (status == DKIM_STAT_OK) { int c; _Bool checked = FALSE; const char *cd; const char *domain = NULL; unsigned char digest[SHA_DIGEST_LENGTH]; char errbuf[BUFRSZ + 1]; # ifdef USE_GNUTLS (void) gnutls_hash_deinit(dfc->mctx_hash, digest); # else /* USE_GNUTLS */ SHA1_Final(digest, &dfc->mctx_hash); # endif /* USE_GNUTLS */ for (c = 0; c < nsigs; c++) { if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) == 0 || (dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_TESTKEY) != 0 || dkim_sig_getbh(sigs[c]) != DKIM_SIGBH_MATCH) continue; checked = TRUE; cd = dkim_sig_getdomain(sigs[c]); status = dkimf_rep_check(conf->conf_rep, sigs[c], dfc->mctx_spam, digest, SHA_DIGEST_LENGTH, &limit, &ratio, &count, &spam, errbuf, sizeof errbuf); if (status == 1) { domain = cd; break; } else if (status == -1) { if (conf->conf_dolog) { cd = dkim_sig_getdomain(sigs[c]); syslog(LOG_NOTICE, "%s: reputation query for \"%s\" failed: %s", dfc->mctx_jobid, cd, errbuf); } return dkimf_miltercode(ctx, conf->conf_handling.hndl_reperr, NULL); } else if (conf->conf_repverbose && conf->conf_dolog) { if (status == 2) { syslog(LOG_NOTICE, "%s: no reputation data available for \"%s\"", dfc->mctx_jobid, cd); } else { syslog(LOG_INFO, "%s: allowed by reputation of %s (%f, count %lu, spam %lu, limit %lu)", dfc->mctx_jobid, cd, ratio, count, spam, limit); } } } if (domain == NULL && !checked) { status = dkimf_rep_check(conf->conf_rep, NULL, dfc->mctx_spam, digest, SHA_DIGEST_LENGTH, &limit, &ratio, &count, &spam, errbuf, sizeof errbuf); if (status == 1) { domain = "NULL domain"; } else if (status == -1) { if (conf->conf_dolog) { syslog(LOG_NOTICE, "%s: reputation query for NULL domain failed: %s", dfc->mctx_jobid, errbuf); } return dkimf_miltercode(ctx, conf->conf_handling.hndl_reperr, NULL); } else if (conf->conf_repverbose && conf->conf_dolog) { if (status == 2) { syslog(LOG_NOTICE, "%s: no reputation data available for NULL domain", dfc->mctx_jobid); } else { syslog(LOG_INFO, "%s: allowed by reputation of NULL domain (%f, count %lu, spam %lu, limit %lu)", dfc->mctx_jobid, ratio, count, spam, limit); } } } if (domain != NULL) { if (dolog) { syslog(LOG_NOTICE, "%s: %sblocked by reputation of %s (%f, count %lu, spam %lu, limit %lu)", dfc->mctx_jobid, conf->conf_reptest ? "would be " : "", domain, ratio, count, spam, limit); } if (!conf->conf_reptest) { if (dkimf_setreply(ctx, REPDENYSMTP, REPDENYESC, REPDENYTXT) != MI_SUCCESS && conf->conf_dolog) { syslog(LOG_NOTICE, "%s: smfi_setreply() failed", dfc->mctx_jobid); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } } } #endif /* _FFR_REPUTATION */ if (dfc->mctx_addheader) { u_char val[MAXADDRESS + 1]; /* ** Record DKIM and ADSP results in an ** Authentication-Results: header field. */ memset(val, '\0', sizeof val); memset(header, '\0', sizeof header); snprintf((char *) header, sizeof header, "%s%s", cc->cctx_noleadspc ? " " : "", authservid); if (conf->conf_authservidwithjobid && dfc->mctx_jobid != NULL) { strlcat((char *) header, "/", sizeof header); strlcat((char *) header, (char *) dfc->mctx_jobid, sizeof header); } strlcat((char *) header, ";", sizeof header); strlcat((char *) header, DELIMITER, sizeof header); if (dfc->mctx_status == DKIMF_STATUS_GOOD || dfc->mctx_status == DKIMF_STATUS_BAD || dfc->mctx_status == DKIMF_STATUS_REVOKED || dfc->mctx_status == DKIMF_STATUS_PARTIAL || dfc->mctx_status == DKIMF_STATUS_NOKEY || dfc->mctx_status == DKIMF_STATUS_VERIFYERR) { dkimf_ar_all_sigs(header, sizeof header, dfc->mctx_tmpstr, dfc->mctx_dkimv, conf, &dfc->mctx_status); } else if (dfc->mctx_status == DKIMF_STATUS_NOSIGNATURE) { strlcat((char *) header, "dkim=none", sizeof header); } #ifdef _FFR_ATPS strlcat((char *) header, ";", sizeof header); strlcat((char *) header, DELIMITER, sizeof header); strlcat((char *) header, "dkim-atps=", sizeof header); switch (dfc->mctx_atps) { case DKIM_ATPS_UNKNOWN: strlcat((char *) header, "neutral", sizeof header); break; case DKIM_ATPS_NOTFOUND: strlcat((char *) header, "fail", sizeof header); break; case DKIM_ATPS_FOUND: strlcat((char *) header, "pass", sizeof header); break; default: assert(0); } #endif /* _FFR_ATPS */ /* if we generated either, pretty it up */ if (header[0] != '\0') { _Bool first; int len; char *p; char *last; char tmphdr[DKIM_MAXHEADER + 1]; c = sizeof AUTHRESULTSHDR + 2; first = TRUE; memset(tmphdr, '\0', sizeof tmphdr); for (p = strtok_r((char *) header, DELIMITER, &last); p != NULL; p = strtok_r(NULL, DELIMITER, &last)) { len = strlen(p); if (!first) { if (c + len >= DKIM_HDRMARGIN) { strlcat(tmphdr, "\n\t", sizeof tmphdr); c = 8; } else { strlcat(tmphdr, " ", sizeof tmphdr); } } strlcat(tmphdr, p, sizeof tmphdr); first = FALSE; c += len; } strlcpy((char *) dfc->mctx_dkimar, tmphdr, sizeof dfc->mctx_dkimar); dkimf_add_ar_fields(dfc, conf, ctx); #ifdef _FFR_RESIGN if (dfc->mctx_resign) { snprintf(header, sizeof header, "%s: %s", AUTHRESULTSHDR, dfc->mctx_dkimar); status = dkimf_msr_header(dfc->mctx_srhead, &lastdkim, header, strlen(header)); if (status != DKIM_STAT_OK) { return dkimf_libstatus(ctx, lastdkim, "dkim_header()", status); } status = dkimf_msr_eoh(dfc->mctx_srhead, &lastdkim); if (status != DKIM_STAT_OK) { return dkimf_libstatus(ctx, lastdkim, "dkim_eoh()", status); } } #endif /* _FFR_RESIGN */ } } #ifdef _FFR_RATE_LIMIT /* enact rate limiting */ if (conf->conf_ratelimitdb != NULL && conf->conf_flowdatadb != NULL) { int exceeded = 0; int nvalid = 0; int nsigs = 0; unsigned int limit; DKIM_SIGINFO **sigs; if (dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs) == DKIM_STAT_OK) { for (c = 0; c < nsigs; c++) { if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) == 0 && dkim_sig_getbh(sigs[c]) != DKIM_SIGBH_MATCH) continue; nvalid++; if (dkimf_rate_check(dkim_sig_getdomain(sigs[c]), conf->conf_ratelimitdb, conf->conf_flowdatadb, conf->conf_flowfactor, conf->conf_flowdatattl, &limit) == 1) { exceeded++; if (conf->conf_dolog) { syslog(LOG_ERR, "%s: rate limit for '%s' (%u) exceeded", dfc->mctx_jobid, dkim_sig_getdomain(sigs[c]), limit); } } } } if (nvalid == 0) { if (dkimf_rate_check(NULL, conf->conf_ratelimitdb, conf->conf_flowdatadb, conf->conf_flowfactor, conf->conf_flowdatattl, &limit) == 1) { exceeded++; if (conf->conf_dolog) { syslog(LOG_ERR, "%s: rate limit for unsigned mail (%u) exceeded", dfc->mctx_jobid, limit); } } } if (exceeded > 0) return SMFIS_TEMPFAIL; } #endif /* _FFR_RATE_LIMIT */ /* send an ARF message for DKIM? */ if (dfc->mctx_status == DKIMF_STATUS_BAD && conf->conf_sendreports) dkimf_sigreport(cc, conf, hostname); #ifdef _FFR_VBR if (dkimf_valid_vbr(dfc)) { _Bool add_vbr_header = FALSE; _Bool vbr_validsig = FALSE; VBR_STAT vbr_status = VBR_STAT_OK; int c; int nsigs; char *vbr_result; char *vbr_domain; char *vbr_certifier; char *vbr_vouchers; char *vbr_type; char *p; char *sctx; char *eq; u_char *param; u_char *value; DKIM_SIGINFO **sigs; Header vbr_header; char tmp[DKIM_MAXHEADER + 1]; for (c = 0; ; c++) { vbr_header = dkimf_findheader(dfc, VBR_INFOHEADER, c); if (vbr_header == NULL) break; vbr_result = "none"; vbr_domain = NULL; vbr_certifier = NULL; vbr_vouchers = NULL; vbr_type = NULL; /* break out the VBR-Info header contents */ strlcpy(tmp, vbr_header->hdr_val, sizeof tmp); for (p = strtok_r(tmp, ";", &sctx); p != NULL; p = strtok_r(NULL, ";", &sctx)) { eq = strchr(p, '='); if (eq == NULL) continue; *eq = '\0'; for (param = (u_char *) p; *param != '\0'; param++) { if (!(isascii(*param) && isspace(*param))) break; } dkimf_trimspaces(param); for (value = (u_char *) eq + 1; *value != '\0'; value++) { if (!(isascii(*value) && isspace(*value))) break; } dkimf_trimspaces(value); if (strcasecmp((char *) param, "md") == 0) { vbr_domain = (char *) value; } else if (strcasecmp((char *) param, "mc") == 0) { vbr_type = (char *) value; } else if (strcasecmp((char *) param, "mv") == 0) { vbr_vouchers = (char *) value; } } /* confirm a valid signature was there */ if (dfc->mctx_dkimv != NULL && dkim_getsiglist(dfc->mctx_dkimv, &sigs, &nsigs) == DKIM_STAT_OK) { u_char *d; for (c = 0; c < nsigs; c++) { d = dkim_sig_getdomain(sigs[c]); if (strcasecmp((char *) d, vbr_domain) == 0 && (dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0 && dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MATCH) { vbr_validsig = TRUE; break; } } } if (vbr_validsig) { /* use accessors to set parsed values */ vbr_setcert(dfc->mctx_vbr, (u_char *) vbr_vouchers); vbr_settype(dfc->mctx_vbr, (u_char *) vbr_type); vbr_setdomain(dfc->mctx_vbr, (u_char *) vbr_domain); /* attempt the query */ vbr_status = vbr_query(dfc->mctx_vbr, (u_char **) &vbr_result, (u_char **) &vbr_certifier); } switch (vbr_status) { case VBR_STAT_DNSERROR: if (conf->conf_dolog) { const char *err; err = (const char *) vbr_geterror(dfc->mctx_vbr); syslog(LOG_NOTICE, "%s: can't verify VBR information%s%s", dfc->mctx_jobid, err == NULL ? "" : ": ", err == NULL ? "" : err); } add_vbr_header = TRUE; vbr_result = "temperror"; break; case VBR_STAT_INVALID: case VBR_STAT_NORESOURCE: if (conf->conf_dolog) { const char *err; err = (const char *) vbr_geterror(dfc->mctx_vbr); syslog(LOG_NOTICE, "%s: error handling VBR information%s%s", dfc->mctx_jobid, err == NULL ? "" : ": ", err == NULL ? "" : err); } add_vbr_header = TRUE; if (vbr_status == VBR_STAT_INVALID) vbr_result = "temperror"; else vbr_result = "permerror"; break; case VBR_STAT_OK: add_vbr_header = TRUE; break; default: assert(0); } if (add_vbr_header) { snprintf((char *) header, sizeof header, "%s%s%s%s vbr=%s header.md=%s", cc->cctx_noleadspc ? " " : "", authservid, conf->conf_authservidwithjobid ? "/" : "", conf->conf_authservidwithjobid ? (char *) dfc->mctx_jobid : "", vbr_result, vbr_domain); if (vbr_certifier != NULL) { strlcat(header, " header.mv=", sizeof header); strlcat(header, vbr_certifier, sizeof header); } if (dkimf_insheader(ctx, 1, AUTHRESULTSHDR, (char *) header) == MI_FAILURE) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header add failed", dfc->mctx_jobid, AUTHRESULTSHDR); } } break; } } } #endif /* _FFR_VBR */ if (conf->conf_redirect != NULL && dfc->mctx_status == DKIMF_STATUS_BAD) { struct addrlist *a; /* convert all recipients to headers */ for (a = dfc->mctx_rcptlist; a != NULL; a = a->a_next) { if (dkimf_delrcpt(ctx, a->a_addr) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: smfi_delrcpt() failed", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } snprintf(header, sizeof header, "rfc822;%s", a->a_addr); if (dkimf_addheader(ctx, ORCPTHEADER, header) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: smfi_addheader() failed", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } } /* add our recipient */ if (dkimf_addrcpt(ctx, conf->conf_redirect) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: smfi_addrcpt() failed", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } } } #ifdef USE_LUA if (conf->conf_finalscript != NULL) { _Bool dofree = TRUE; struct dkimf_lua_script_result lres; memset(&lres, '\0', sizeof lres); dfc->mctx_mresult = SMFIS_CONTINUE; status = dkimf_lua_final_hook(ctx, conf->conf_finalfunc, conf->conf_finalfuncsz, "final script", &lres, NULL, NULL); if (status != 0) { if (conf->conf_dolog) { if (lres.lrs_error == NULL) { dofree = FALSE; switch (status) { case 2: lres.lrs_error = "processing error"; break; case 1: lres.lrs_error = "syntax error"; break; case -1: lres.lrs_error = "memory allocation error"; break; default: lres.lrs_error = "unknown error"; break; } } syslog(LOG_ERR, "%s: dkimf_lua_final_hook() failed: %s", dfc->mctx_jobid, lres.lrs_error); } if (dofree) free(lres.lrs_error); return SMFIS_TEMPFAIL; } if (dfc->mctx_mresult != SMFIS_CONTINUE && dfc->mctx_mresult != SMFIS_ACCEPT) return dfc->mctx_mresult; } #endif /* USE_LUA */ /* complete signing if requested */ #ifdef _FFR_RESIGN if (dfc->mctx_srhead != NULL && (!dfc->mctx_resign || conf->conf_resignall || dfc->mctx_status == DKIMF_STATUS_GOOD)) #else /* _FFR_RESIGN */ if (dfc->mctx_srhead != NULL) #endif /* _FFR_RESIGN */ { size_t len; u_char *start; struct signreq *sr; status = dkimf_msr_eom(dfc->mctx_srhead, &lastdkim); if (status != DKIM_STAT_OK) { dkimf_log_ssl_errors(lastdkim, NULL, (char *) dfc->mctx_jobid); return dkimf_libstatus(ctx, lastdkim, "dkim_eom()", status); } if (dfc->mctx_tmpstr == NULL) { dfc->mctx_tmpstr = dkimf_dstring_new(BUFRSZ, 0); if (dfc->mctx_tmpstr == NULL) { syslog(LOG_WARNING, "%s: dkimf_dstring_new() failed", dfc->mctx_jobid); return SMFIS_TEMPFAIL; } } else { dkimf_dstring_blank(dfc->mctx_tmpstr); } for (sr = dfc->mctx_srhead; sr != NULL; sr = sr->srq_next) { dkimf_dstring_blank(dfc->mctx_tmpstr); if (cc->cctx_noleadspc) dkimf_dstring_cat1(dfc->mctx_tmpstr, ' '); lastdkim = sr->srq_dkim; status = dkim_getsighdr_d(sr->srq_dkim, strlen(DKIM_SIGNHEADER) + 2, &start, &len); if (status != DKIM_STAT_OK) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: dkim_getsighdr() failed", dfc->mctx_jobid); } return SMFIS_TEMPFAIL; } /* XXX -- check "len" for oversize? */ dkimf_stripcr((char *) start); dkimf_dstring_cat(dfc->mctx_tmpstr, start); if (dkimf_insheader(ctx, 1, DKIM_SIGNHEADER, (char *) dkimf_dstring_get(dfc->mctx_tmpstr)) == MI_FAILURE) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header add failed", dfc->mctx_jobid, DKIM_SIGNHEADER); } } else if (conf->conf_dolog_success) { char *d; char *s; if (sr->srq_domain != NULL) d = sr->srq_domain; else d = dfc->mctx_domain; if (sr->srq_selector != NULL) s = sr->srq_selector; else s = conf->conf_selector; syslog(LOG_INFO, "%s: %s field added (s=%s, d=%s)", dfc->mctx_jobid, DKIM_SIGNHEADER, s, d); } } #ifdef _FFR_VBR /* add VBR-Info header if generated */ if (dfc->mctx_vbrinfo != NULL) { if (dkimf_insheader(ctx, 1, VBR_INFOHEADER, dfc->mctx_vbrinfo) == MI_FAILURE) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header add failed", dfc->mctx_jobid, VBR_INFOHEADER); } } } if (conf->conf_vbr_purge && dfc->mctx_vbrpurge) { if (dkimf_chgheader(ctx, VBRTYPEHEADER, 0, NULL) != MI_SUCCESS || conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header remove failed", dfc->mctx_jobid, VBRTYPEHEADER); } if (dkimf_chgheader(ctx, VBRCERTHEADER, 0, NULL) != MI_SUCCESS || conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header remove failed", dfc->mctx_jobid, VBRCERTHEADER); } } #endif /* _FFR_VBR */ } /* ** Identify the filter, if requested. */ if (conf->conf_addswhdr) { char xfhdr[DKIM_MAXHEADER + 1]; memset(xfhdr, '\0', sizeof xfhdr); snprintf(xfhdr, DKIM_MAXHEADER, "%s%s v%s %s %s", cc->cctx_noleadspc ? " " : "", DKIMF_PRODUCT, VERSION, hostname, dfc->mctx_jobid != NULL ? dfc->mctx_jobid : (u_char *) JOBIDUNKNOWN); if (dkimf_insheader(ctx, 1, SWHEADERNAME, xfhdr) != MI_SUCCESS) { if (conf->conf_dolog) { syslog(LOG_ERR, "%s: %s header add failed", dfc->mctx_jobid, SWHEADERNAME); } dkimf_cleanup(ctx); return SMFIS_TEMPFAIL; } } if (lastdkim != NULL) dkimf_log_ssl_errors(lastdkim, sig, (char *) dfc->mctx_jobid); /* ** If we got this far, we're ready to complete. */ ret = SMFIS_ACCEPT; /* translate the stored status */ switch (dfc->mctx_status) { case DKIMF_STATUS_GOOD: break; case DKIMF_STATUS_BAD: ret = dkimf_libstatus(ctx, lastdkim, "mlfi_eom()", DKIM_STAT_BADSIG); if ((ret == SMFIS_REJECT || ret == SMFIS_TEMPFAIL || ret == SMFIS_DISCARD) && testkey) ret = SMFIS_ACCEPT; break; case DKIMF_STATUS_NOKEY: ret = dkimf_libstatus(ctx, lastdkim, "mlfi_eom()", DKIM_STAT_NOKEY); break; case DKIMF_STATUS_REVOKED: ret = dkimf_libstatus(ctx, lastdkim, "mlfi_eom()", DKIM_STAT_REVOKED); break; case DKIMF_STATUS_NOSIGNATURE: if (!dfc->mctx_addheader) { ret = dkimf_libstatus(ctx, lastdkim, "mlfi_eom()", DKIM_STAT_NOSIG); } break; case DKIMF_STATUS_BADFORMAT: ret = SMFIS_ACCEPT; break; case DKIMF_STATUS_UNKNOWN: break; default: if (status != DKIM_STAT_OK) ret = dkimf_libstatus(ctx, NULL, "mlfi_eom()", status); break; } return ret; } /* ** MLFI_ABORT -- handler called if an earlier filter in the filter process ** rejects the message ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_abort(SMFICTX *ctx) { dkimf_cleanup(ctx); return SMFIS_CONTINUE; } /* ** MLFI_CLOSE -- handler called on connection shutdown ** ** Parameters: ** ctx -- milter context ** ** Return value: ** An SMFIS_* constant. */ sfsistat mlfi_close(SMFICTX *ctx) { connctx cc; dkimf_cleanup(ctx); cc = (connctx) dkimf_getpriv(ctx); if (cc != NULL) { pthread_mutex_lock(&conf_lock); cc->cctx_config->conf_refcnt--; if (cc->cctx_config->conf_refcnt == 0 && cc->cctx_config != curconf) dkimf_config_free(cc->cctx_config); pthread_mutex_unlock(&conf_lock); free(cc); dkimf_setpriv(ctx, NULL); } #ifdef QUERY_CACHE if (querycache) { time_t now; (void) time(&now); if (cache_lastlog + CACHESTATSINT < now) { u_int c_hits; u_int c_queries; u_int c_expired; u_int c_pct; u_int c_keys; dkim_getcachestats(cc->cctx_config->conf_libopendkim, &c_queries, &c_hits, &c_expired, &c_keys, FALSE); cache_lastlog = now; if (c_queries == 0) c_pct = 0; else c_pct = (c_hits * 100) / c_queries; syslog(LOG_INFO, "cache: %u quer%s, %u hit%s (%d%%), %u expired, %u key%s", c_queries, c_queries == 1 ? "y" : "ies", c_hits, c_hits == 1 ? "" : "s", c_pct, c_expired, c_keys, c_keys == 1 ? "" : "s"); } } #endif /* QUERY_CACHE */ return SMFIS_CONTINUE; } /* ** smfilter -- the milter module description */ struct smfiDesc smfilter = { DKIMF_PRODUCT, /* filter name */ SMFI_VERSION, /* version code -- do not change */ 0, /* flags; updated in main() */ mlfi_connect, /* connection info filter */ #if SMFI_VERSION == 2 mlfi_helo, /* SMTP HELO command filter */ #else /* SMFI_VERSION == 2 */ NULL, /* SMTP HELO command filter */ #endif /* SMFI_VERSION == 2 */ mlfi_envfrom, /* envelope sender filter */ mlfi_envrcpt, /* envelope recipient filter */ mlfi_header, /* header filter */ mlfi_eoh, /* end of header */ mlfi_body, /* body block filter */ mlfi_eom, /* end of message */ mlfi_abort, /* message aborted */ mlfi_close, /* shutdown */ #if SMFI_VERSION > 2 NULL, /* unrecognised command */ #endif #if SMFI_VERSION > 3 NULL, /* DATA */ #endif #if SMFI_VERSION >= 0x01000000 mlfi_negotiate /* negotiation callback */ #endif }; /* ** USAGE -- print a usage message and return the appropriate exit status ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE. */ static int usage(void) { fprintf(stderr, "%s: usage: %s -p socketfile [options]\n" "\t-A \tauto-restart\n" "\t-b modes \tselect operating modes\n" "\t-c canon \tcanonicalization to use when signing\n" "\t-d domlist \tdomains to sign\n" "\t-D \talso sign subdomains\n" "\t-e name \textract configuration value and exit\n" "\t-f \tdon't fork-and-exit\n" "\t-F time \tfixed timestamp to use when signing (test mode only)\n" "\t-k keyfile \tlocation of secret key file\n" "\t-l \tlog activity to system log\n" "\t-L limit \tsignature limit requirements\n" "\t-n \tcheck configuration and exit\n" "\t-o hdrlist \tlist of headers to omit from signing\n" "\t-P pidfile \tfile into which to write process ID\n" "\t-q \tquarantine messages that fail to verify\n" "\t-Q \tquery test mode\n" "\t-r \trequire basic RFC5322 header compliance\n" "\t-s selector \tselector to use when signing\n" "\t-S signalg \tsignature algorithm to use when signing\n" "\t-t testfile \tevaluate RFC5322 message in \"testfile\"\n" "\t-T timeout \tDNS timeout (seconds)\n" "\t-u userid \tchange to specified userid\n" "\t-v \tincrease verbosity during testing\n" "\t-V \tprint version number and terminate\n" "\t-W \t\"why?!\" mode (log sign/verify decision logic)\n" "\t-x conffile \tread configuration from conffile\n", progname, progname); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Process command line arguments and call the milter mainline. */ int main(int argc, char **argv) { _Bool autorestart = FALSE; _Bool gotp = FALSE; _Bool dofork = TRUE; _Bool stricttest = FALSE; _Bool configonly = FALSE; _Bool querytest = FALSE; int c; int status; int n; int verbose = 0; int maxrestarts = 0; int maxrestartrate_n = 0; int filemask = -1; int mdebug = 0; #ifdef HAVE_SMFI_VERSION u_int mvmajor; u_int mvminor; u_int mvrelease; #endif /* HAVE_SMFI_VERSION */ time_t now; gid_t gid = (gid_t) -1; sigset_t sigset; uint64_t fixedtime = (uint64_t) -1; time_t maxrestartrate_t = 0; pthread_t rt; unsigned long tmpl; const char *args = CMDLINEOPTS; FILE *f; struct passwd *pw = NULL; struct group *gr = NULL; char *become = NULL; char *chrootdir = NULL; char *extract = NULL; char *p; char *pidfile = NULL; #ifdef POPAUTH char *popdbfile = NULL; #endif /* POPAUTH */ char *testfile = NULL; char *testpubkeys = NULL; struct config *cfg = NULL; char *end; char argstr[MAXARGV]; char err[BUFRSZ + 1]; /* initialize */ reload = FALSE; testmode = FALSE; #ifdef QUERY_CACHE querycache = FALSE; #endif /* QUERY_CACHE */ sock = NULL; #ifdef POPAUTH popdb = NULL; #endif /* POPAUTH */ no_i_whine = TRUE; conffile = NULL; memset(myhostname, '\0', sizeof myhostname); (void) gethostname(myhostname, sizeof myhostname); progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; (void) time(&now); srandom(now); curconf = dkimf_config_new(); if (curconf == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_OSERR; } /* process command line options */ while ((c = getopt(argc, argv, args)) != -1) { switch (c) { case 'A': autorestart = TRUE; break; case 'b': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_modestr = optarg; break; case 'c': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_canonstr = optarg; break; case 'd': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_domlist = strdup(optarg); if (curconf->conf_domlist == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); return EX_SOFTWARE; } break; case 'D': curconf->conf_subdomains = TRUE; break; case 'e': extract = optarg; break; case 'f': dofork = FALSE; break; case 'F': if (optarg == NULL || *optarg == '\0') return usage(); errno = 0; if (optarg[0] == '-') { errno = ERANGE; fixedtime = ULONG_MAX; } else { fixedtime = strtoul(optarg, &p, 10); } if (fixedtime == (uint64_t) ULONG_MAX || errno != 0 || *p != '\0') { fprintf(stderr, "%s: invalid time value\n", progname); return EX_USAGE; } break; case 'k': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_keyfile = optarg; break; case 'l': curconf->conf_dolog = TRUE; break; case 'L': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_siglimit = optarg; break; case 'n': configonly = TRUE; break; case 'o': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_omitlist = optarg; break; case 'p': if (optarg == NULL || *optarg == '\0') return usage(); sock = optarg; (void) smfi_setconn(optarg); gotp = TRUE; break; case 'P': if (optarg == NULL || *optarg == '\0') return usage(); pidfile = optarg; break; case 'Q': querytest = TRUE; testmode = TRUE; break; case 'r': curconf->conf_reqhdrs = TRUE; break; case 's': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_selector = (u_char *) optarg; break; case 'S': if (optarg == NULL || *optarg == '\0') return usage(); curconf->conf_signalgstr = optarg; break; case 't': if (optarg == NULL || *optarg == '\0') return usage(); testmode = TRUE; testfile = optarg; break; case 'T': if (optarg == NULL || *optarg == '\0') return usage(); errno = 0; if (optarg[0] == '-') { errno = ERANGE; tmpl = ULONG_MAX; } else { tmpl = strtoul(optarg, &p, 10); } if (tmpl == ULONG_MAX || errno != 0 || *p != '\0') { fprintf(stderr, "%s: invalid value for -%c\n", progname, c); return EX_USAGE; } curconf->conf_dnstimeout = (unsigned int) tmpl; break; case 'u': if (optarg == NULL || *optarg == '\0') return usage(); become = optarg; break; case 'v': verbose++; break; case 'V': if (!dkimf_config_setlib(curconf, &p)) { fprintf(stderr, "%s: can't configure DKIM library: %s\n", progname, p); return EX_SOFTWARE; } printf("%s: %s v%s\n", progname, DKIMF_PRODUCT, VERSION); #ifdef USE_GNUTLS printf("\tCompiled with GnuTLS %s\n", GNUTLS_VERSION); #else /* USE_GNUTLS */ printf("\tCompiled with %s\n", SSLeay_version(SSLEAY_VERSION)); #endif /* USE_GNUTLS */ printf("\tSMFI_VERSION 0x%x\n", SMFI_VERSION); #ifdef HAVE_SMFI_VERSION (void) smfi_version(&mvmajor, &mvminor, &mvrelease); printf("\tlibmilter version %d.%d.%d\n", mvmajor, mvminor, mvrelease); #endif /* HAVE_SMFI_VERSION */ printf("\tSupported signing algorithms:\n"); for (c = 0; dkimf_sign[c].str != NULL; c++) { if (dkimf_sign[c].code != DKIM_SIGN_RSASHA256 || dkim_libfeature(curconf->conf_libopendkim, DKIM_FEATURE_SHA256)) printf("\t\t%s\n", dkimf_sign[c].str); } printf("\tSupported canonicalization algorithms:\n"); for (c = 0; dkimf_canon[c].str != NULL; c++) printf("\t\t%s\n", dkimf_canon[c].str); dkimf_optlist(stdout); return EX_OK; case 'W': curconf->conf_logwhy = TRUE; break; case 'x': if (optarg == NULL || *optarg == '\0') return usage(); else conffile = optarg; break; case 'X': allowdeprecated = TRUE; break; default: return usage(); } } if (optind != argc) return usage(); #ifdef USE_GNUTLS if (dkim_ssl_version() != GNUTLS_VERSION_NUMBER * 256) #else /* USE_GNUTLS */ if (dkim_ssl_version() != OPENSSL_VERSION_NUMBER) #endif /* USE_GNUTLS */ { fprintf(stderr, "%s: incompatible SSL versions (library = 0x%09lx, filter = %09lx)\n", progname, dkim_ssl_version(), #ifdef USE_GNUTLS (unsigned long) GNUTLS_VERSION_NUMBER * 256); #else /* USE_GNUTLS */ (unsigned long) OPENSSL_VERSION_NUMBER); #endif /* USE_GNUTLS */ return EX_SOFTWARE; } /* if there's a default config file readable, use it */ if (conffile == NULL && access(DEFCONFFILE, R_OK) == 0) { conffile = DEFCONFFILE; if (verbose > 1) { fprintf(stderr, "%s: using default configfile %s\n", progname, DEFCONFFILE); } } if (conffile != NULL) { u_int line = 0; char *missing; char *deprecated = NULL; char path[MAXPATHLEN + 1]; cfg = config_load(conffile, dkimf_config, &line, path, sizeof path, &deprecated); if (cfg == NULL) { fprintf(stderr, "%s: %s: configuration error at line %u: %s\n", progname, path, line, config_error()); dkimf_config_free(curconf); return EX_CONFIG; } #ifdef DEBUG (void) config_dump(cfg, stdout, NULL); #endif /* DEBUG */ missing = config_check(cfg, dkimf_config); if (missing != NULL) { fprintf(stderr, "%s: %s: required parameter \"%s\" missing\n", progname, conffile, missing); config_free(cfg); dkimf_config_free(curconf); return EX_CONFIG; } if (deprecated != NULL) { char *action = "aborting"; if (allowdeprecated) action = "continuing"; fprintf(stderr, "%s: %s: settings found for deprecated value(s): %s; %s\n", progname, conffile, deprecated, action); if (!allowdeprecated) { config_free(cfg); dkimf_config_free(curconf); return EX_CONFIG; } } } if (dkimf_config_load(cfg, curconf, err, sizeof err, become) != 0) { if (conffile == NULL) conffile = "(stdin)"; fprintf(stderr, "%s: %s: %s\n", progname, conffile, err); config_free(cfg); dkimf_config_free(curconf); return EX_CONFIG; } if (configonly) { config_free(cfg); dkimf_config_free(curconf); return EX_OK; } if (extract) { int ret = EX_OK; if (cfg != NULL) { if (!config_validname(dkimf_config, extract)) ret = EX_DATAERR; else if (config_dump(cfg, stdout, extract) == 0) ret = EX_CONFIG; config_free(cfg); dkimf_config_free(curconf); } return ret; } dolog = curconf->conf_dolog; curconf->conf_data = cfg; #ifdef _FFR_REPUTATION /* power up the reputation code */ repute_init(); if (curconf->conf_reptimeout != 0L) repute_set_timeout(curconf->conf_reptimeout); #endif /* _FFR_REPUTATION */ if (querytest) { _Bool exists = FALSE; DKIMF_DB dbtest; DKIMF_DBDATA dbdp; char *p; char dbname[BUFRSZ + 1]; char query[BUFRSZ + 1]; char **result; if (isatty(0)) { fprintf(stdout, "%s: enter data set description\n", progname); fprintf(stdout, "\tcsl:entry1[,entry2[,...]]\n" "\tfile:path\n" "\trefile:path\n" "\tdb:path\n" #ifdef USE_ODBX "\tdsn:://[user[:pwd]@][port+]host/dbase[/key=val[?...]]\n" #endif /* USE_ODBX */ #ifdef USE_LDAP "\tldapscheme://host[:port][/dn[?attrs[?scope[?filter[?exts]]]]]\n" #endif /* USE_LDAP */ #ifdef USE_LUA "\tlua:path\n" #endif /* USE_LUA */ #ifdef USE_LIBMEMCACHED "\tmemcache:host[:port][,...]/prefix\n" #endif /* USE_LIBMEMCACHED */ #ifdef _FFR_REPUTATION "\trepute:server[:reporter]\n" #endif /* _FFR_REPUTATION */ #ifdef _FFR_SOCKETDB "\tsocket:{ port@host | path}\n" #endif /* _FFR_SOCKETDB */ #ifdef USE_MDB "\tmdb:path\n" #endif /* USE_MDB */ #ifdef USE_ERLANG "\terlang:node@host[,...]:cookie:module:function\n" #endif /* USE_ERLANG */ "> "); } memset(dbname, '\0', sizeof dbname); if (fgets(dbname, BUFRSZ, stdin) != dbname) { fprintf(stderr, "%s: fgets(): %s\n", progname, strerror(errno)); return EX_OSERR; } p = strchr(dbname, '\n'); if (p != NULL) *p = '\0'; for (p = dbname; isspace(*p); p++) continue; if (p != dbname) memmove(dbname, p, strlen(p) + 1); p = NULL; status = dkimf_db_open(&dbtest, dbname, (DKIMF_DB_FLAG_READONLY | DKIMF_DB_FLAG_ASCIIONLY), NULL, &p); if (status != 0) { fprintf(stderr, "%s: %s: dkimf_db_open(): %s\n", progname, dbname, p); return EX_SOFTWARE; } for (;;) { if (isatty(0)) { fprintf(stdout, "%s: enter 'query/n' where 'n' is number of fields to request\n> ", progname); } memset(query, '\0', sizeof query); if (fgets(query, BUFRSZ, stdin) != query) break; p = strchr(query, '\n'); if (p != NULL) *p = '\0'; if (dkimf_isblank(query)) continue; p = strchr(query, '/'); if (p == NULL) { (void) dkimf_db_close(dbtest); fprintf(stderr, "%s: invalid query '%s'\n", progname, query); return EX_USAGE; } n = atoi(p + 1); if (n < 0) { (void) dkimf_db_close(dbtest); fprintf(stderr, "%s: invalid query '%s'\n", progname, query); return EX_USAGE; } result = (char **) malloc(sizeof(char *) * n); if (result == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_OSERR; } for (c = 0; c < n; c++) { result[c] = (char *) malloc(BUFRSZ + 1); if (result[c] == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); free(result); return EX_OSERR; } memset(result[c], '\0', BUFRSZ + 1); } dbdp = (DKIMF_DBDATA) malloc(sizeof(struct dkimf_db_data) * n); if (dbdp == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); free(result); return EX_OSERR; } for (c = 0; c < n; c++) { dbdp[c].dbdata_buffer = result[c]; dbdp[c].dbdata_buflen = BUFRSZ; dbdp[c].dbdata_flags = 0; } *p = '\0'; status = dkimf_db_get(dbtest, query, strlen(query), dbdp, n, &exists); if (status != 0) { char errbuf[BUFRSZ + 1]; memset(errbuf, '\0', sizeof errbuf); dkimf_db_strerror(dbtest, errbuf, sizeof errbuf); fprintf(stderr, "%s: dkimf_db_get() returned %d: \"%s\"\n", progname, status, errbuf); } else if (!exists) { fprintf(stdout, "%s: dkimf_db_get(): record not found\n", progname); } else { for (c = 0; c < n; c++) { if (dbdp[c].dbdata_buflen == 0) fprintf(stdout, "\n"); else if (dbdp[c].dbdata_buflen == (size_t) -1) fprintf(stdout, "\n"); else fprintf(stdout, "'%s'\n", result[c]); } } for (c = 0; c < n; c++) free(result[c]); free(result); free(dbdp); } fprintf(stdout, "\n"); dkimf_db_close(dbtest); return 0; } if (testmode && curconf->conf_modestr == NULL) curconf->conf_mode = DKIMF_MODE_VERIFIER; /* ** Use values found in the configuration file, if any. Note that ** these are operational parameters for the filter (e.g which socket ** to use which userid to become, etc.) and aren't reloaded upon a ** reload signal. Reloadable values are handled via the ** dkimf_config_load() function, which has already been called. */ if (cfg != NULL) { if (!autorestart) { (void) config_get(cfg, "AutoRestart", &autorestart, sizeof autorestart); } if (autorestart) { char *rate = NULL; (void) config_get(cfg, "AutoRestartCount", &maxrestarts, sizeof maxrestarts); (void) config_get(cfg, "AutoRestartRate", &rate, sizeof rate); if (rate != NULL) { time_t t; char *q; p = strchr(rate, '/'); if (p == NULL) { fprintf(stderr, "%s: AutoRestartRate invalid\n", progname); config_free(cfg); return EX_CONFIG; } *p = '\0'; n = strtol(rate, &q, 10); if (n < 0 || *q != '\0') { fprintf(stderr, "%s: AutoRestartRate invalid\n", progname); config_free(cfg); return EX_CONFIG; } t = (time_t) strtoul(p + 1, &q, 10); switch (*q) { case 'd': case 'D': t *= 86400; break; case 'h': case 'H': t *= 3600; break; case 'm': case 'M': t *= 60; break; case '\0': case 's': case 'S': break; default: t = 0; break; } if (*q != '\0' && *(q + 1) != '\0') t = 0; if (t == 0) { fprintf(stderr, "%s: AutoRestartRate invalid\n", progname); config_free(cfg); return EX_CONFIG; } maxrestartrate_n = n; maxrestartrate_t = t; } } if (dofork) { (void) config_get(cfg, "Background", &dofork, sizeof dofork); } (void) config_get(cfg, "TestPublicKeys", &testpubkeys, sizeof testpubkeys); (void) config_get(cfg, "StrictTestMode", &stricttest, sizeof stricttest); (void) config_get(cfg, "MilterDebug", &mdebug, sizeof mdebug); if (!gotp) { (void) config_get(cfg, "Socket", &sock, sizeof sock); if (sock != NULL) { gotp = TRUE; (void) smfi_setconn(sock); } } if (pidfile == NULL) { (void) config_get(cfg, "PidFile", &pidfile, sizeof pidfile); } #ifdef QUERY_CACHE (void) config_get(cfg, "QueryCache", &querycache, sizeof querycache); #endif /* QUERY_CACHE */ (void) config_get(cfg, "UMask", &filemask, sizeof filemask); if (become == NULL) { (void) config_get(cfg, "Userid", &become, sizeof become); } #ifdef POPAUTH if (popdbfile == NULL) { (void) config_get(cfg, "POPDBFile", &popdbfile, sizeof popdbfile); } #endif /* POPAUTH */ (void) config_get(cfg, "ChangeRootDirectory", &chrootdir, sizeof chrootdir); } #ifndef SMFIF_QUARANTINE if (quarantine) { fprintf(stderr, "%s: quarantine service not available\n", progname); return EX_SOFTWARE; } #endif /* ! SMFIF_QUARANTINE */ if (!gotp && !testmode) { fprintf(stderr, "%s: milter socket must be specified\n", progname); if (argc == 1) fprintf(stderr, "\t(use \"-?\" for help)\n"); return EX_CONFIG; } /* suppress a bunch of things if we're in test mode */ if (testmode) { curconf->conf_dolog = FALSE; curconf->conf_sendreports = FALSE; autorestart = FALSE; dofork = FALSE; become = NULL; pidfile = NULL; chrootdir = NULL; } dkimf_setmaxfd(); /* prepare to change user if appropriate */ if (become != NULL) { char *colon; /* see if there was a group specified; if so, validate */ colon = strchr(become, ':'); if (colon != NULL) { *colon = '\0'; gr = getgrnam(colon + 1); if (gr == NULL) { char *q; gid = (gid_t) strtol(colon + 1, &q, 10); if (*q == '\0') gr = getgrgid(gid); if (gr == NULL) { if (curconf->conf_dolog) { syslog(LOG_ERR, "no such group or gid '%s'", colon + 1); } fprintf(stderr, "%s: no such group '%s'\n", progname, colon + 1); return EX_DATAERR; } } } /* validate the user */ pw = getpwnam(become); if (pw == NULL) { char *q; uid_t uid; uid = (uid_t) strtoul(become, &q, 10); if (*q == '\0') pw = getpwuid(uid); if (pw == NULL) { if (curconf->conf_dolog) { syslog(LOG_ERR, "no such user or uid '%s'", become); } fprintf(stderr, "%s: no such user '%s'\n", progname, become); return EX_DATAERR; } } if (gr == NULL) gid = pw->pw_gid; else gid = gr->gr_gid; (void) endpwent(); #ifdef _FFR_REPUTATION /* chown things that need chowning */ if (curconf->conf_rep != NULL) { (void) dkimf_rep_chown_cache(curconf->conf_rep, pw->pw_uid); } #endif /* _FFR_REPUTATION */ } /* change root if requested */ if (chrootdir != NULL) { /* warn if doing so as root without then giving up root */ if (become == NULL && getuid() == 0) { if (curconf->conf_dolog) { syslog(LOG_WARNING, "using ChangeRootDirectory without Userid not advised"); } fprintf(stderr, "%s: use of ChangeRootDirectory without Userid not advised\n", progname); } /* change to the new root first */ if (chdir(chrootdir) != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "%s: chdir(): %s", chrootdir, strerror(errno)); } fprintf(stderr, "%s: %s: chdir(): %s\n", progname, chrootdir, strerror(errno)); return EX_OSERR; } /* now change the root */ if (chroot(chrootdir) != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "%s: chroot(): %s", chrootdir, strerror(errno)); } fprintf(stderr, "%s: %s: chroot(): %s\n", progname, chrootdir, strerror(errno)); return EX_OSERR; } } if (curconf->conf_enablecores) { _Bool enabled = FALSE; #ifdef __linux__ if (prctl(PR_SET_DUMPABLE, 1) == -1) { if (curconf->conf_dolog) { syslog(LOG_ERR, "prctl(): %s", strerror(errno)); } fprintf(stderr, "%s: prctl(): %s\n", progname, strerror(errno)); } else { enabled = TRUE; } #endif /* __linux__ */ if (!enabled) { if (curconf->conf_dolog) { syslog(LOG_WARNING, "can't enable coredumps; continuing"); } fprintf(stderr, "%s: can't enable coredumps; continuing\n", progname); } } die = FALSE; if (autorestart) { _Bool quitloop = FALSE; int restarts = 0; int status; pid_t pid; pid_t wpid; struct sigaction sa; if (dofork) { pid = fork(); switch (pid) { case -1: if (curconf->conf_dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "fork(): %s", strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); dkimf_zapkey(curconf); return EX_OSERR; case 0: dkimf_stdio(); break; default: dkimf_zapkey(curconf); return EX_OK; } } if (pidfile != NULL) { f = fopen(pidfile, "w"); if (f != NULL) { fprintf(f, "%ld\n", (long) getpid()); (void) fclose(f); } else { if (curconf->conf_dolog) { syslog(LOG_ERR, "can't write pid to %s: %s", pidfile, strerror(errno)); } } } sa.sa_handler = dkimf_sighandler; /* XXX -- HAHAHAH => sa.sa_sigaction = NULL; */ sigemptyset(&sa.sa_mask); sigaddset(&sa.sa_mask, SIGHUP); sigaddset(&sa.sa_mask, SIGINT); sigaddset(&sa.sa_mask, SIGTERM); sigaddset(&sa.sa_mask, SIGUSR1); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) != 0 || sigaction(SIGINT, &sa, NULL) != 0 || sigaction(SIGTERM, &sa, NULL) != 0 || sigaction(SIGUSR1, &sa, NULL) != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "[parent] sigaction(): %s", strerror(errno)); } } /* now enact the user change */ if (become != NULL) { /* make all the process changes */ if (getuid() != pw->pw_uid) { if (initgroups(pw->pw_name, gid) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "initgroups(): %s", strerror(errno)); fprintf(stderr, "%s: initgroups(): %s", progname, strerror(errno)); return EX_NOPERM; } else if (setgid(gid) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "setgid(): %s", strerror(errno)); fprintf(stderr, "%s: setgid(): %s", progname, strerror(errno)); return EX_NOPERM; } else if (setuid(pw->pw_uid) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "setuid(): %s", strerror(errno)); fprintf(stderr, "%s: setuid(): %s", progname, strerror(errno)); return EX_NOPERM; } } } if (maxrestartrate_n > 0) dkimf_restart_check(maxrestartrate_n, 0); while (!quitloop) { status = dkimf_socket_cleanup(sock); if (status != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "[parent] socket cleanup failed: %s", strerror(status)); } return EX_UNAVAILABLE; } pid = fork(); switch (pid) { case -1: if (curconf->conf_dolog) { syslog(LOG_ERR, "fork(): %s", strerror(errno)); } dkimf_zapkey(curconf); return EX_OSERR; case 0: sa.sa_handler = SIG_DFL; if (sigaction(SIGHUP, &sa, NULL) != 0 || sigaction(SIGINT, &sa, NULL) != 0 || sigaction(SIGTERM, &sa, NULL) != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "[child] sigaction(): %s", strerror(errno)); } } quitloop = TRUE; break; default: for (;;) { wpid = wait(&status); if (wpid == -1 && errno == EINTR) { if (die) { dkimf_killchild(pid, diesig, curconf->conf_dolog); dkimf_zapkey(curconf); while (wpid != pid) wpid = wait(&status); if (pidfile != NULL) (void) unlink(pidfile); exit(EX_OK); } else if (reload) { dkimf_killchild(pid, SIGUSR1, curconf->conf_dolog); reload = FALSE; continue; } } if (pid != wpid) continue; if (wpid != -1 && curconf->conf_dolog) { if (WIFSIGNALED(status)) { syslog(LOG_NOTICE, "terminated with signal %d, restarting", WTERMSIG(status)); } else if (WIFEXITED(status)) { if (WEXITSTATUS(status) == EX_CONFIG || WEXITSTATUS(status) == EX_SOFTWARE) { syslog(LOG_NOTICE, "exited with status %d", WEXITSTATUS(status)); quitloop = TRUE; } else { syslog(LOG_NOTICE, "exited with status %d, restarting", WEXITSTATUS(status)); } } } if (conffile != NULL) reload = TRUE; break; } break; } if (maxrestarts > 0 && restarts >= maxrestarts) { if (curconf->conf_dolog) { syslog(LOG_ERR, "maximum restart count exceeded"); } return EX_UNAVAILABLE; } if (maxrestartrate_n > 0 && maxrestartrate_t > 0 && !dkimf_restart_check(0, maxrestartrate_t)) { if (curconf->conf_dolog) { syslog(LOG_ERR, "maximum restart rate exceeded"); } return EX_UNAVAILABLE; } restarts++; } } if (!autorestart && dofork) { pid_t pid; pid = fork(); switch (pid) { case -1: if (curconf->conf_dolog) { int saveerrno; saveerrno = errno; syslog(LOG_ERR, "fork(): %s", strerror(errno)); errno = saveerrno; } fprintf(stderr, "%s: fork(): %s\n", progname, strerror(errno)); dkimf_zapkey(curconf); return EX_OSERR; case 0: dkimf_stdio(); break; default: dkimf_zapkey(curconf); return EX_OK; } } /* write out the pid */ if (!autorestart && pidfile != NULL) { f = fopen(pidfile, "w"); if (f != NULL) { fprintf(f, "%ld\n", (long) getpid()); (void) fclose(f); } else { if (curconf->conf_dolog) { syslog(LOG_ERR, "can't write pid to %s: %s", pidfile, strerror(errno)); } } } /* ** Block SIGUSR1 for use of our reload thread, and SIGHUP, SIGINT ** and SIGTERM for use of libmilter's signal handling thread. */ sigemptyset(&sigset); sigaddset(&sigset, SIGUSR1); sigaddset(&sigset, SIGHUP); sigaddset(&sigset, SIGTERM); sigaddset(&sigset, SIGINT); status = pthread_sigmask(SIG_BLOCK, &sigset, NULL); if (status != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "pthread_sigmask(): %s", strerror(status)); } fprintf(stderr, "%s: pthread_sigmask(): %s\n", progname, strerror(status)); dkimf_zapkey(curconf); return EX_OSERR; } /* now enact the user change */ if (!autorestart && become != NULL) { /* make all the process changes */ if (getuid() != pw->pw_uid) { if (initgroups(pw->pw_name, gid) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "initgroups(): %s", strerror(errno)); fprintf(stderr, "%s: initgroups(): %s", progname, strerror(errno)); return EX_NOPERM; } else if (setgid(gid) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "setgid(): %s", strerror(errno)); fprintf(stderr, "%s: setgid(): %s", progname, strerror(errno)); return EX_NOPERM; } else if (setuid(pw->pw_uid) != 0) { if (curconf->conf_dolog) syslog(LOG_ERR, "setuid(): %s", strerror(errno)); fprintf(stderr, "%s: setuid(): %s", progname, strerror(errno)); return EX_NOPERM; } } } /* initialize DKIM library */ if (!dkimf_config_setlib(curconf, &p)) { if (curconf->conf_dolog) syslog(LOG_ERR, "can't configure DKIM library: %s", p); fprintf(stderr, "%s: can't configure DKIM library: %s", progname, p); return EX_SOFTWARE; } if (filemask != -1) (void) umask((mode_t) filemask); if (mdebug > 0) (void) smfi_setdbg(mdebug); if (!testmode) { /* try to clean up the socket */ status = dkimf_socket_cleanup(sock); if (status != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "socket cleanup failed: %s", strerror(status)); } fprintf(stderr, "%s: socket cleanup failed: %s\n", progname, strerror(status)); dkimf_zapkey(curconf); if (!autorestart && pidfile != NULL) (void) unlink(pidfile); return EX_UNAVAILABLE; } smfilter.xxfi_flags = SMFIF_ADDHDRS; if (curconf->conf_redirect != NULL) { smfilter.xxfi_flags |= SMFIF_ADDRCPT; smfilter.xxfi_flags |= SMFIF_DELRCPT; } #ifdef SMFIF_SETSYMLIST smfilter.xxfi_flags |= SMFIF_SETSYMLIST; #endif /* SMFIF_SETSYMLIST */ if (curconf->conf_remarall || !curconf->conf_keepar || #ifdef _FFR_IDENTITY_HEADER curconf->conf_rmidentityhdr || #endif /* _FFR_IDENTITY_HEADER */ #ifdef _FFR_VBR curconf->conf_vbr_purge || #endif /* _FFR_VBR */ curconf->conf_remsigs) smfilter.xxfi_flags |= SMFIF_CHGHDRS; #ifdef SMFIF_QUARANTINE if (curconf->conf_capture) smfilter.xxfi_flags |= SMFIF_QUARANTINE; #endif /* SMFIF_QUARANTINE */ /* register with the milter interface */ if (smfi_register(smfilter) == MI_FAILURE) { if (curconf->conf_dolog) syslog(LOG_ERR, "smfi_register() failed"); fprintf(stderr, "%s: smfi_register() failed\n", progname); dkimf_zapkey(curconf); if (!autorestart && pidfile != NULL) (void) unlink(pidfile); return EX_UNAVAILABLE; } #ifdef HAVE_SMFI_OPENSOCKET /* try to establish the milter socket */ if (smfi_opensocket(FALSE) == MI_FAILURE) { if (curconf->conf_dolog) syslog(LOG_ERR, "smfi_opensocket() failed"); fprintf(stderr, "%s: smfi_opensocket() failed\n", progname); dkimf_zapkey(curconf); return EX_UNAVAILABLE; } #endif /* HAVE_SMFI_OPENSOCKET */ } /* initialize libcrypto mutexes */ if (!curconf->conf_disablecryptoinit) { status = dkimf_crypto_init(); if (status != 0) { fprintf(stderr, "%s: error initializing crypto library: %s\n", progname, strerror(status)); } } if ((curconf->conf_mode & DKIMF_MODE_VERIFIER) != 0 && !dkim_libfeature(curconf->conf_libopendkim, DKIM_FEATURE_SHA256)) { if (curconf->conf_allowsha1only) { if (dolog) { syslog(LOG_WARNING, "WARNING: verifier mode operating without rsa-sha256 support"); } } else { if (dolog) { syslog(LOG_ERR, "verifier mode operating without rsa-sha256 support; terminating"); } fprintf(stderr, "%s: verify mode requires rsa-sha256 support\n", progname); if (!autorestart && pidfile != NULL) (void) unlink(pidfile); return EX_CONFIG; } } /* set up for test mode if selected */ if (testpubkeys != NULL) { dkim_query_t qtype = DKIM_QUERY_FILE; (void) dkim_options(curconf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_QUERYMETHOD, &qtype, sizeof qtype); (void) dkim_options(curconf->conf_libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_QUERYINFO, testpubkeys, strlen(testpubkeys)); } pthread_mutex_init(&conf_lock, NULL); pthread_mutex_init(&pwdb_lock, NULL); /* perform test mode */ if (testfile != NULL) { status = dkimf_testfiles(curconf->conf_libopendkim, testfile, fixedtime, stricttest, verbose); dkim_close(curconf->conf_libopendkim); return status; } memset(argstr, '\0', sizeof argstr); end = &argstr[sizeof argstr - 1]; n = sizeof argstr; for (c = 1, p = argstr; c < argc && p < end; c++) { if (strchr(argv[c], ' ') != NULL) { status = snprintf(p, n, "%s \"%s\"", c == 1 ? "args:" : "", argv[c]); } else { status = snprintf(p, n, "%s %s", c == 1 ? "args:" : "", argv[c]); } p += status; n -= status; } #ifdef POPAUTH if (popdbfile != NULL) { char *err = NULL; status = dkimf_initpopauth(); if (status != 0) { fprintf(stderr, "%s: can't initialize popauth mutex: %s\n", progname, strerror(status)); syslog(LOG_ERR, "can't initialize mutex: %s", popdbfile); } status = dkimf_db_open(&popdb, popdbfile, DKIMF_DB_FLAG_READONLY, NULL, &err); if (status != 0) { fprintf(stderr, "%s: can't open database %s: %s\n", progname, popdbfile, err); if (dolog) { syslog(LOG_ERR, "can't open database %s: %s", popdbfile, err); } dkimf_zapkey(curconf); if (!autorestart && pidfile != NULL) (void) unlink(pidfile); return EX_UNAVAILABLE; } } #endif /* POPAUTH */ #ifdef _FFR_STATS dkimf_stats_init(); #endif /* _FFR_STATS */ if (curconf->conf_dolog) { syslog(LOG_INFO, "%s v%s starting (%s)", DKIMF_PRODUCT, VERSION, argstr); } /* spawn the SIGUSR1 handler */ status = pthread_create(&rt, NULL, dkimf_reloader, NULL); if (status != 0) { if (curconf->conf_dolog) { syslog(LOG_ERR, "pthread_create(): %s", strerror(status)); } if (!autorestart && pidfile != NULL) (void) unlink(pidfile); return EX_OSERR; } /* call the milter mainline */ errno = 0; status = smfi_main(); if (curconf->conf_dolog) { syslog(LOG_INFO, "%s v%s terminating with status %d, errno = %d", DKIMF_PRODUCT, VERSION, status, errno); } #ifdef POPAUTH if (popdb != NULL) dkimf_db_close(popdb); #endif /* POPAUTH */ dkimf_zapkey(curconf); /* tell the reloader thread to die */ die = TRUE; (void) raise(SIGUSR1); if (!autorestart && pidfile != NULL) (void) unlink(pidfile); dkimf_crypto_free(); dkimf_config_free(curconf); return status; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.conf.5.in000066400000000000000000001272401337314105200235160ustar00rootroot00000000000000.TH opendkim.conf 5 "The Trusted Domain Project" .SH NAME .B opendkim.conf \- Configuration file for opendkim .SH LOCATION .I @SYSCONFDIR@/opendkim.conf .SH DESCRIPTION .I opendkim(8) implements the .B DKIM specification for signing and verifying e-mail messages on a per-domain basis. This file is its configuration file. Blank lines are ignored. Lines containing a hash ("#") character are truncated at the hash character to allow for comments in the file. Other content should be the name of a parameter, followed by white space, followed by the value of that parameter, each on a separate line. For parameters that are Boolean in nature, only the first byte of the value is processed. For positive values, the following are accepted: "T", "t", "Y", "y", "1". For negative values, the following are accepted: "F", "f", "N", "n", "0". Many, but not all, of these parameters are also available as command line options to .I opendkim(8). However, new parameters are generally not added as command line options so the complete set of options is available here, and thus use of the configuration file is encouraged. In some future release, the set of available command line options is likely to get trimmed. See the .I opendkim(8) man page for details about how and when the configuration file contents are reloaded. Some of these parameters are listed as having a type of "dataset". See the .I opendkim(8) man page for a description of such parameters. Unless otherwise stated, Boolean values default to "false", integer values default to 0, and string and dataset values default to being undefined. .SH PARAMETERS .TP .I AllowSHA1Only (Boolean) Permit verify mode when only SHA1 support is available. RFC6376 requires that verifiers implement both SHA1 and SHA256 support. Setting this feature changes the absence of SHA256 support from an error to a warning. .TP .I AlwaysAddARHeader (Boolean) Add an "Authentication-Results:" header field even to unsigned messages from domains with no "signs all" policy. The reported DKIM result will be "none" in such cases. Normally unsigned mail from non-strict domains does not cause the results header field to be added. .TP .I AuthservID (string) Sets the "authserv-id" to use when generating the Authentication-Results: header field after verifying a message. The default is to use the name of the MTA processing the message. If the string "HOSTNAME" is provided, the name of the host running the filter (as returned by the .I gethostname(3) function) will be used. .TP .I AuthservIDWithJobID (Boolean) If "true", requests that the authserv-id portion of the added Authentication-Results: header fields contain the job ID of the message being evaluated. .TP .I AutoRestart (Boolean) Automatically re-start on failures. Use with caution; if the filter fails instantly after it starts, this can cause a tight .I fork(2) loop. .TP .I AutoRestartCount (integer) Sets the maximum automatic restart count. After this number of automatic restarts, the filter will give up and terminate. A value of 0 implies no limit; this is the default. .TP .I AutoRestartRate (string) Sets the maximum automatic restart rate. If the filter begins restarting faster than the rate defined here, it will give up and terminate. This is a string of the form .I n/t[u] where .I n is an integer limiting the count of restarts in the given interval and .I t[u] defines the time interval through which the rate is calculated; .I t is an integer and .I u defines the units thus represented ("s" or "S" for seconds, the default; "m" or "M" for minutes; "h" or "H" for hours; "d" or "D" for days). For example, a value of "10/1h" limits the restarts to 10 in one hour. There is no default, meaning restart rate is not limited. .TP .I Background (Boolean) Causes .I opendkim to fork and exits immediately, leaving the service running in the background. The default is "true". .TP .I BaseDirectory (string) If set, instructs the filter to change to the specified directory using .I chdir(2) before doing anything else. This means any files referenced elsewhere in the configuration file can be specified relative to this directory. It's also useful for arranging that any crash dumps will be saved to a specific location. .TP .I BodyLengthDB (dataset) Requests that .I opendkim include a "l=" body length tag when the set contains any of the envelope recipient addresses. The addresses presented are tested against the database in various forms as described under the .I SigningTable setting (below). This feature of the protocol exists to improve the likelihood that a signature will survive transit through a mailing list server, as they commonly append footers to messages. Note, however, that this creates a potential security issue since someone could add arbitrary text to the signed message and the signature would still validate. See the DKIM specification for details. .TP .I BogusKey (string) Instructs the filter to treat a passing signature associated with a bogus (forged) key in a special way. Possible values are .I neutral (return a "neutral" result), .I none (take no special action) and .I fail (return a "fail" result; this is the default). @UNBOUND_MANNOTICE@ .TP .I CaptureUnknownErrors (Boolean) When set, and on systems where MTA quarantine is available, the filter will request quarantine of a message that results in an internal error or resource exhaustion. .TP .I Canonicalization (string) Selects the canonicalization method(s) to be used when signing messages. When verifying, the message's DKIM-Signature: header field specifies the canonicalization method. The recognized values are .I relaxed and .I simple as defined by the DKIM specification. The default is .I simple. The value may include two different canonicalizations separated by a slash ("/") character, in which case the first will be applied to the header and the second to the body. .TP .I ChangeRootDirectory (string) Requests that the operating system change the effective root directory of the process to the one specified here prior to beginning execution. .BR chroot (2) requires superuser access. A warning will be generated if .I UserID is not also set. .TP .I ClockDrift (integer) Sets the tolerance in seconds to be applied when determining whether a signature was either expired or generated in the future. The default is 300. .TP .I Diagnostics (Boolean) Requests the inclusion of "z=" tags in signatures, which encode the original header field set for use by verifiers when diagnosing verification failures. Not recommended for normal operation. .TP .I DiagnosticDirectory (string) Directory into which to write diagnostic reports when message verification fails on a message bearing a "z=" tag. If not set (the default), these files are not generated. .TP .I DisableCryptoInit (Boolean) If set, skips initialization of the SSL library initialization steps, which are normally required in multi-threaded environments. This assumes some other library opendkim is using will do the required initialization and shutdown. .TP .I DNSConnect (Boolean) Requests that the asynchronous resolver start using TCP immediately rather than using UDP until TCP is actually needed. Does not work with all resolvers. .TP .I DNSTimeout (integer) Sets the DNS timeout in seconds. A value of 0 causes an infinite wait. The default is 5. Ignored if not using an asynchronous resolver package. See also the NOTES section below. .TP .I Domain (dataset) A set of domains whose mail should be signed by this filter. Mail from other domains will be verified rather than being signed. This parameter is not required if a .I SigningTable is in use; in that case, the list of signed domains is implied by the lines in that file. This parameter is ignored if a .I KeyTable is defined. .TP .I DomainKeysCompat (boolean) If set, backward compatibility with DomainKeys (RFC4870) key records is enabled. When not set, such keys are considered to be syntactically invalid. .TP .I DontSignMailTo (dataset) A set of e-mail address, mail to which should never be signed by the filter. Note that this is an "any" feature; if any one of the recipients of the message matches a member of this list, the message will not be signed. .TP .I EnableCoredumps (boolean) On systems that have such support, make an explicit request to the kernel to dump cores when the filter crashes for some reason. Some modern UNIX systems suppress core dumps during crashes for security reasons if the user ID has changed during the lifetime of the process. Currently only supported on Linux. .TP .I ExemptDomains (dataset) Specifies a set of domains, mail from which should be ignored entirely by the filter. This is similar to the .I PeerList setting except that it bases its decision on the sender of the message as identified from the header fields or other message data, not the identity of the SMTP client sending the message. .TP .I ExternalIgnoreList (dataset) Identifies a set of "external" hosts that may send mail through the server as one of the signing domains without credentials as such. This has the effect of suppressing the "external host (hostname) tried to send mail as (domain)" log messages. Entries in the data set should be of the same form as those of the .I PeerList option below. The set is empty by default. .TP .I FinalPolicyScript (string) Gives the name of a Lua script that should be run after the entire message has been received. This can be used to enact local policy decisions such as message rejection, quarantine, rerouting, etc. based on signatures found on the message, the results of attempts to verify them, and other properties of the message or signatures. See .I opendkim-lua(3) for details. @LUA_MANNOTICE@ .TP .I FixCRLF (Boolean) Requests that the DKIM library convert bare CRs and LFs to CRLFs during body canonicalization, anticipating that an MTA somewhere before delivery will do that conversion anyway. The default is to leave them as-is. .TP .I IdentityHeader (string) This specifies the header field where an identity is stored. @IDENTITY_HEADER_MANNOTICE@ .TP .I IdentityHeaderRemove (Boolean) Remove the .I IdentityHeader after signing. @IDENTITY_HEADER_MANNOTICE@ .TP .I IgnoreMalformedMail (boolean) Silently passes malformed messages without alteration. This includes messages that fail the .I RequiredHeaders check, if enabled. The default is to pass those messages but add an Authentication-Results field indicating that they were malformed. .TP .I Include (string) Names a file to be opened and read as an additional configuration file. Nesting is allowed to a maximum of five levels. .TP .I InternalHosts (dataset) Identifies a set internal hosts whose mail should be signed rather than verified. Entries in this data set follow the same form as those of the .I PeerList option below. If not specified, the default of "127.0.0.1" is applied. Naturally, providing a value here overrides the default, so if mail from 127.0.0.1 should be signed, the list provided here should include that address explicitly. .TP .I KeepAuthResults (boolean) Suppresses removal of Authentication-Results header fields containing DKIM results apparently added by this filter (usually the result of a misconfiguration or a forgery). .TP .I KeepTemporaryFiles (boolean) Instructs the filter to create temporary files containing the header and body canonicalizations of messages that are signed or verified. The location of these files can be set using the .I TemporaryDirectory parameter. Intended only for debugging verification problems. .TP .I KeyFile (string) Gives the location of a PEM-formatted private key to be used for signing all messages. Ignored if a .I KeyTable is defined. .TP .I KeyTable (dataset) Gives the location of a file mapping key names to signing keys. If present, overrides any .I KeyFile setting in the configuration file. The data set named here maps each key name to three values: (a) the name of the domain to use in the signature's "d=" value; (b) the name of the selector to use in the signature's "s=" value; and (c) either a private key or a path to a file containing a private key. If the first value consists solely of a percent sign ("%") character, it will be replaced by the apparent domain of the sender when generating a signature. If the third value starts with a slash ("/") character, or "./" or "../", then it is presumed to refer to a file from which the private key should be read, otherwise it is itself a PEM-encoded private key or a base64-encoded DER private key; a "%" in the third value in this case will be replaced by the apparent domain name of the sender. The .I SigningTable (see below) is used to select records from this table to be used to add signatures based on the message sender. .TP .I LDAPAuthMechanism (string) Names the authentication mechanism to use when connecting to an LDAP server. The default is the empty string, meaning "simple" authentication should be done. .TP .I LDAPAuthName (string) Specifies the authenticating name to use when using SASL to authenticate to an LDAP server. Requires SASL support be installed on the local system. There is no default. .TP .I LDAPAuthRealm (string) Specifies the authentication realm to use when using SASL to authenticate to an LDAP server. Requires SASL support be installed on the local system. There is no default. .TP .I LDAPAuthUser (string) Specifies the authenticating user to use when using SASL to authenticate to an LDAP server. Requires SASL support be installed on the local system. There is no default. .TP .I LDAPBindPassword (string) Specifies the password to use when conducting an LDAP "bind" operation. There is no default. .TP .I LDAPBindUser (string) Specifies the user ID to use when conducting an LDAP "bind" operation. There is no default. .TP .I LDAPDisableCache (Boolean) Suppresses creation of a local cache in front of LDAP queries. .TP .I LDAPKeepaliveIdle (integer) Sets the number of seconds a connection to an LDAP server needs to remain idle before TCP starts sending keepalive probes. If not specified, the LDAP library default is used. .TP .I LDAPKeepaliveInterval (integer) Sets the interval in seconds between TCP keepalive probes. If not specified, the LDAP library default is used. .TP .I LDAPKeepaliveProbes (integer) Sets the maximum number of keepalive probes TCP should send before abandoning the connection. If not specified, the LDAP library default is used. .TP .I LDAPTimeout (integer) Sets the time in seconds after which an LDAP operation should be abandoned. The default is 5. .TP .I LDAPUseTLS (Boolean) Indicates whether or not a TLS connection should be established when contacting an LDAP server. The default is "False". .TP .I LogResults (boolean) If logging is enabled (see .I Syslog below), requests that the results of evaluation of all signatures that were at least partly intact (i.e., the "d=", "s=", and "b=" tags could be extracted). .TP .I LogWhy (boolean) If logging is enabled (see .I Syslog below), issues very detailed logging about the logic behind the filter's decision to either sign a message or verify it. The logic behind the decision is non-trivial and can be confusing to administrators not familiar with its operation. A description of how the decision is made can be found in the OPERATIONS section of the .I opendkim(8) man page. This causes a large increase in the amount of log data generated for each message, so it should be limited to debugging use and not enabled for general operation. .TP .I MacroList (dataset) Defines a set of MTA-provided .I macros that should be checked to see if the sender has been determined to be a local user and therefore whether or not the message should be signed. If a .I value is specified matching a macro name in the data set, the value of the macro must match a value specified (matching is case-sensitive), otherwise the macro must be defined but may contain any value. The set is empty by default, meaning macros are not considered when making the sign-verify decision. The general format of the value is .I value1[|value2[|...]]; if one or more value is defined then the macro must be set to one of the listed values, otherwise the macro must be set but can contain any value. In order for the macro and its value to be available to the filter for checking, the MTA must send it during the protocol exchange. This is either accomplished via manual configuration of the MTA to send the desired macros or, for MTA/filter combinations that support the feature, the filter can request those macros that are of interest. The latter is a feature negotiated at the time the filter receives a connection from the MTA and its availability depends upon the version of milter used to compile the filter and the version of the MTA making the connection. This data set must be of type "file" or "csl". .TP .I MaximumHeaders (integer) Defines the maximum number of bytes the header block of a message may consume before the filter will reject the message. This mitigates a denial-of-service attack in which a client connects to the MTA and begins feeding an unbounded number of header fields of arbitrary size; since the filter keeps a cache of these, the attacker could cause the filter to allocate an unspecified amount of memory. The default is 65536; a value of 0 removes the limit. .TP .I MaximumSignaturesToVerify (integer) Defines the maximum number of signatures on a message for which verification should be conducted. The default is three. Signatures are selected from the top of the message downward. If .I TrustSignaturesFrom is set, signatures from domains in that data set are always verified, which may consume part or all of, or even exceed, this limit. .TP .I MaximumSignedBytes (integer) Specifies the maximum number of bytes of message body to be signed. Messages shorter than this limit will be signed in their entirety. Setting this value implies use of .I BodyLengthDB for all addresses. .TP .I MilterDebug (integer) Sets the debug level to be requested from the milter library. Currently, the highest meaningful value is 6. .TP .I Minimum (string) Instructs the verification code to fail messages for which a partial signature was received. There are three possible formats: .I min indicating at least .I min bytes of the message must be signed (or if the message is smaller than .I min then all of it must be signed); .I min% requiring that at least .I min percent of the received message must be signed; and .I min+ meaning there may be no more than .I min bytes of unsigned data appended to the message for it to be considered valid. .TP .I MinimumKeyBits (integer) Establishes a minimum key size for acceptable signatures. Signatures with smaller key sizes, even if they otherwise pass DKIM validation, will me marked as invalid. The default is 1024. A value of 0 accepts all keys. .TP .I Mode (string) Selects operating modes. The string is a concatenation of characters that indicate which mode(s) of operation are desired. Valid modes are .I s (signer) and .I v (verifier). The default is .I sv except in test mode (see the .I opendkim(8) man page) in which case the default is .I v. When signing mode is enabled, one of the following combinations must also be set: (a) Domain, KeyFile, Selector, no KeyTable, no SigningTable; (b) KeyTable, SigningTable, no Domain, no KeyFile, no Selector; (c) KeyTable, SetupPolicyScript, no Domain, no KeyFile, no Selector. .TP .I MTA (dataset) A set of MTA names (a la the .I sendmail(8) DaemonPortOptions Name parameter) whose mail should be signed by this filter. There is no default, meaning MTA name is not considered when making the sign-verify decision. .TP .I MTACommand (string) Specifies the path to an executable to be used for sending mail such as that generated by .I SendReports. The default is @SENDMAIL_PATH@. The executable should accept typical .B sendmail(8) command line options "\-t" (take addresses from message body) and "\-f" (set envelope sender), accept the new message on its standard input, and return a non-zero exit status on any error. .TP .I MultipleSignatures (Boolean) Allow addition of multiple signatures when a signing table is in use. See .I SigningTable for more information. .TP .I MustBeSigned (dataset) Specifies a set of header fields that, if present, must be covered by the DKIM signature when verifying a message. If a header field in this set is present in the message and is not signed, the filter will treat even an otherwise valid signature as invalid. The default is an empty list. .TP .I Nameservers (string) Provides a comma-separated list of IP addresses that are to be used when doing DNS queries to retrieve DKIM keys, VBR records, etc. These override any local defaults built in to the resolver in use, which may be defined in .I /etc/resolv.conf or hard-coded into the software. .TP .I NoHeaderB (Boolean) If set, this feature suppresses the use of "header.b" tags in added Authentication-Results header fields. The default is "false", which means those tags will be applied. .TP .I OmitHeaders (dataset) Specifies a set of header fields that should be omitted when generating signatures. If an entry in the list names any header field that is mandated by the DKIM specification, the entry is ignored. A set of header fields is listed in the DKIM specification (RFC6376, Section 5.4) as "SHOULD NOT" be signed; the default list for this parameter contains those fields (Return-Path, Received, Comments, Keywords, Bcc, Resent-Bcc and DKIM-Signature). To omit no headers, simply use the string "." (or any string that will match no header field names). Specifying a list with this parameter replaces the default entirely, unless one entry is "*" in which case the list is interpreted as a delta to the default; for example, "*,+foobar" will use the entire default list plus the name "foobar", while "*,-Bcc" would use the entire default list except for the "Bcc" entry. .TP .I On-BadSignature (string) Selects the action to be taken when a signature fails to validate. Possible values (with abbreviated forms in parentheses): .I accept (a) accept the message; .I discard (d) discard the message; .I quarantine (q) quarantine the message; .I reject (r) reject the message; .I tempfail (t) temp-fail the message. The default is .I accept. Note that the "t" (testing) flag in a DKIM key bypasses this behaviour; a bad signature that references a testing flag will still be delivered, though the added Authentication-Results field will indicate both the failed result and the test mode so that consumers of the message can take appropriate action. .TP .I On-Default (string) Selects the action to be taken when any verification or internal error of any kind is encountered. This is processed before the other "On-" values so it can be used as a blanket setting followed by specific overrides. .TP .I On-DNSError (string) Selects the action to be taken when a transient DNS error is encountered. Possible values are the same as those for .I On-BadSignature. The default is .I tempfail. .TP .I On-InternalError (string) Selects the action to be taken when an internal error of some kind is encountered. Possible values are the same as those for .I On-BadSignature. The default is .I tempfail. .TP .I On-KeyNotFound (string) Selects the action to be taken when the key referenced by a signature is not present in the DNS. Possible values are the same as those for .I On-BadSignature. The default is .I accept. .TP .I On-NoSignature (string) Selects the action to be taken when a message arrives unsigned. Possible values are the same as those for .I On-BadSignature. The default is .I accept. .TP .I On-Security (string) Selects the action to be taken when a message arrives containing properties that may be a security concern. Possible values are the same as those for .I On-BadSignature. The default is .I tempfail. .TP .I On-SignatureError (string) Selects the action to be taken when a message cannot be signed because of issues with the message or the key provided for signing. Possible values are the same as those for .I On-BadSignature. The default is .I reject. .TP .I OversignHeaders (dataset) Specifies a set of header fields that should be included in all signature header lists (the "h=" tag) once more than the number of times they were actually present in the signed message. The set is empty by default. The purpose of this, and especially of listing an absent header field, is to prevent the addition of important fields between the signer and the verifier. Since the verifier would include that header field when performing verification if it had been added by an intermediary, the signed message and the verified message were different and the verification would fail. Note that listing a field name here and not listing it in the .I SignHeaders list is likely to generate invalid signatures. .TP .I PeerList (dataset) Identifies a set of "peers" that identifies clients whose connections should be accepted without processing by this filter. The set should contain on each line a hostname, domain name (e.g. ".example.com"), IP address, an IPv6 address (including an IPv4 mapped address), or a CIDR-style IP specification (e.g. "192.168.1.0/24"). An entry beginning with a bang ("!") character means "not", allowing exclusions of specific hosts that are otherwise members of larger sets. Host and domain names are matched first, then the IP or IPv6 address depending on the connection type. More precise entries are preferred over less precise ones, i.e. "192.168.1.1" will match before "!192.168.1.0/24". The text form of IPv6 addresses will be forced to lowercase when queried (RFC5952), so the contents of this data set should also use lowercase. The IP address portion of an entry may optionally contain square brackets; both forms (with and without) will be checked. .TP .I PidFile (string) Specifies the path to a file that should be created at process start containing the process ID. .TP .I POPDBFile (dataset) Requests that the filter consult a set for IP addresses that should be allowed for signing. This feature was designed for POP-before-SMTP datastores. @POPAUTH_MANNOTICE@ .TP .I Quarantine (Boolean) Requests that messages which fail verification be quarantined by the MTA. (Requires a sufficiently recent version of the milter library.) .TP .I QueryCache (Boolean) Instructs the DKIM library to maintain its own local cache of keys and policies retrieved from DNS, rather than relying on the nameserver for caching service. Useful if the nameserver being used by the filter is not local. @QUERY_CACHE_MANNOTICE@ .TP .I RedirectFailuresTo (address) Messages bearing signatures that failed to verify are redirected to the specified address. The original envelope recipient set is recorded in the header before redirection occurs. By default, no redirection is done. .TP .I RemoveARAll (Boolean) Removes all Authentication-Results: header fields that also satisfy the requirements of .I RemoveARFrom below. By default, only those containing a DKIM result are removed. .TP .I RemoveARFrom (dataset) Defines a set of hostnames whose Authentication-Results: header fields should be removed before the message is passed for delivery. By default only those header fields matching the local host's canonical name will be removed. Matching is only done on full hostnames (e.g. "host.example.com") or on domain names (e.g. ".example.com"). .TP .I RemoveOldSignatures (Boolean) Removes all existing signatures when operating in signing mode. .TP .I ReplaceHeaders (data set) Defines a set of header fields that should be affected by the text replacement rules defined by the .I ReplaceRules setting. By default, all header fields are included. @REPLACE_RULES_MANNOTICE@ .TP .I ReplaceRules (string) Specifies a file containing a list of text replacement rules that are applied to the message header fields to replace certain content expected to be changed as the message passes through local MTAs. This can be used to accommodate expected changes such as those made to From: fields by MTA "masquerade" features. Each entry in the file consists of a POSIX regular expression, followed by a tab (ASCII 9), followed by the text that should be used to replace the text matching the expression. The '#' character denotes the beginning of a comment and text from that point on in a single line is ignored. Blank lines are also skipped. @REPLACE_RULES_MANNOTICE@ .TP .I ReportAddress (string) Specifies the string to use in the From: header field for outgoing reports (see .I SendReports below). If not specified, the executing user and local hostname will be used to construct the address. .TP .I ReportBccAddress (string) Specifies address(es) to include in a Bcc: header field on outgoing reports (see .I SendReports below). If multiple addresses are required, they should be comma separated. .TP .I RequestReports (boolean) When signing, includes a request for signature evaluation failures in the signature. (See RFC6651 for details.) .TP .I RequiredHeaders (boolean) Checks all messages for compliance with RFC5322 header field count requirements. Non-compliant messages are rejected. .TP .I RequireSafeKeys (boolean) When reading a key file, a message will be logged if the key file has the read or write bit set other than for the owner or for a group that the executing process is in. With this feature set to "true", the filter will further consider this an error and refuse to make use of the file's contents. The default is "true". .TP .I ResignAll (boolean) Where .I ResignMailTo triggers a re-signing action, this flag indicates whether or not all mail should be signed (if set) versus only verified mail being signed (if not set). @RESIGN_MANNOTICE@ .TP .I ResignMailTo (dataset) Checks each message recipient against the specified dataset for a matching record. The full address is checked in each case, then the hostname, then each domain preceded by ".". If there is a match, the value returned is presumed to be the name of a key in the .I KeyTable (if defined) to be used to re-sign the message in addition to verifying it. If there is a match without a .I KeyTable, the default key is applied. @RESIGN_MANNOTICE@ .TP .I ResolverConfiguration (string) Provides the given string as configuration information to the underlying resolver. For the standard UNIX resolver, this is unused; for Unbound, the string contains a filename that is considered to be a configuration file. There is no default. .TP .I ResolverTracing (Boolean) Requests resolver tracing features be enabled, if available. The effect of this depends on how debugging features of the resolver might be implemented. Currently only effective with the OpenDKIM asynchronous resolver library. .TP .I ScreenPolicyScript (string) Gives the name of a Lua script that should be run after all of the header fields have been processed for a message; in particular, this is useful after all DKIM signatures have been detected and initial evaluation has been done. The script has access to all of the header fields and connection information and can direct that certain signatures be ignored based on that information. See .I opendkim-lua(3) for details. @LUA_MANNOTICE@ .TP .I SelectCanonicalizationHeader (string) Defines a header field name which, if present, adjusts which canonicalization will be used to generate an outgoing signature. Overrides the .I Canonicalization setting if the header field is present. The default is "X-Canonicalization". .TP .I Selector (string) Defines the name of the selector to be used when signing messages. See the .B DKIM specification for details. Used only when signing with a single key; see the .I SigningTable parameter below for more information. This parameter is ignored if a .I KeyTable is defined. .TP .I SenderHeaders (dataset) Specifies an ordered list of header fields that should be searched to determine the sender of a message. The first header field found is the one whose value is used. This is mainly used when signing for deciding which signing request(s) to make. By default, the "From" header field is the only one checked. See the .I OmitHeaders setting for a description of possible values. .TP .I SenderMacro (string) Use the milter macro string to determine the sender of the message. @SENDER_MACRO_MANNOTICE@ .TP .I SendReports (Boolean) If true, when a signature verification fails and the signature included a reporting request ("r=y") and the signing domain advertises a reporting address (i.e. .I ra=user) in a reporting record in the DNS, the filter will send a structured report to that address containing details needed to reproduce the problem. See RFC6651 for a complete description of this mechanism. .TP .I SetupPolicyScript (string) Gives the name of a Lua script that should be run once all header fields for a message have arrived. The script has access to all of the header fields and connection information and can request DKIM verification or signing based on that information. See .I opendkim-lua(3) for details. @LUA_MANNOTICE@ .TP .I SignatureAlgorithm (string) Selects the signing algorithm to use when generating signatures. Use 'opendkim \-V' to see the list of supported algorithms. The default is .I rsa-sha256 if it is available, otherwise it will be .I rsa-sha1. .TP .I SignatureTTL (integer) Sets the time-to-live, in seconds, of signatures generated by the filter. If not set, no expiration time is added to signatures. .TP .I SignHeaders (dataset) Specifies the set of header fields that should be included when generating signatures. If the list omits any header field that is mandated by the DKIM specification, those fields are implicitly added. By default, those fields listed in the DKIM specification as "SHOULD" be signed (RFC6376, Section 5.4) will be signed by the filter. See the .I OmitHeaders configuration option for more information about the format and interpretation of this field. .TP .I SigningTable (dataset) Defines a table used to select one or more signatures to apply to a message based on the address found in the From: header field. Keys in this table vary depending on the type of table used; values in this data set should include one field that contains a name found in the .I KeyTable (see above) that identifies which key should be used in generating the signature, and an optional second field naming the signer of the message that will be included in the "i=" tag in the generated signature. Note that the "i=" value will not be included in the signature if it conflicts with the signing domain (the "d=" value). If the first field contains only a "%" character, it will be replaced by the domain found in the From: header field. Similarly, within the optional second field, any "%" character will be replaced by the domain found in the From: header field. If this table specifies a regular expression file ("refile"), then the keys are wildcard patterns that are matched against the address found in the From: header field. Entries are checked in the order in which they appear in the file. For all other database types, the full .I user@host is checked first, then simply .I host, then .I user@.domain (with all superdomains checked in sequence, so "foo.example.com" would first check "user@foo.example.com", then "user@.example.com", then "user@.com"), then .I .domain, then .I user@*, and finally .I *. In any case, only the first match is applied, unless .I MultipleSignatures is enabled in which case all matches are applied. .TP .I SMTPURI (string) Specifies a URI (e.g., "smtp://localhost") to which mail should be sent via SMTP when notifications are generated. @LIBCURL_MANNOTICE@ .TP .I Socket (string) Specifies the socket that should be established by the filter to receive connections from .I sendmail(8) in order to provide service. .I socketspec is in one of two forms: .I local:path, which creates a UNIX domain socket at the specified .I path, or .I inet:port[@host] or .I inet6:port[@host] which creates a TCP socket on the specified .I port and in the specified protocol family. If the .I host is not given as either a hostname or an IP address, the socket will be listening on all interfaces. A literal IP address must be enclosed in square brackets. This option is mandatory either in the configuration file or on the command line. .TP .I SoftStart (Boolean) If set, the inability to connect and authenticate to an LDAP or SQL server will not prevent the filter from starting, and reconnections will be attempted for each query. The default is "False". .TP .I SoftwareHeader (Boolean) Causes .I opendkim to add an "DKIM-Filter" header field indicating the presence of this filter in the path of the message from injection to delivery. The product's name, version, and the job ID are included in the header field's contents. Note that the header field is not added if the .I Mode setting causes the message to be ignored (e.g., if only signing mode is enabled and the configuration causes the message not to be signed, or only verify mode is enabled and configuration would otherwise have caused the message to be signed, then it will not have this header field added). .TP .I Statistics (filename) This specifies a file in which to store DKIM transaction statistics. See .I opendkim-stats(8) for a mechanism to parse the file's contents, and .I opendkim-importstats() for a mechanism to translate the file's contents into SQL database insertions. @STATS_MANNOTICE@ .TP .I StatisticsName (string) Defines the name to be used as the reporting host in statistics logs. By default, the local host's name returned by .I gethostname(3) is used. @STATS_MANNOTICE@ .TP .I StatisticsPolicyScript (string) The statistics script is run after all of the DKIM verification and signing work has been completed but before any final message handling is done. The main purpose of this script is to give the user an opportunity to examine the message or its signatures and make arbitrary additional statistical observations that should be recorded by the statistics module. .TP .I StatisticsPrefix (string) When .I AnonymousStatistics is enabled, this string may be specified and will be prepended to all data before hashing for more complete anonymization. This means two records from different sources referencing the same source will still produce different hashes, meaning such correlation is now only possible within the data from a single repoter. .TP .I StrictHeaders (Boolean) If set, instructs the DKIM library to refuse processing of a message if the header field count does not conform to RFC5322 Section 3.6. .TP .I StrictTestMode (Boolean) Selects strict CRLF mode during testing (see the .I -t command line flag in the .I opendkim(8) man page); messages for which all header fields and body lines are not CRLF-terminated are considered malformed and will produce an error. .TP .I SubDomains (Boolean) Sign subdomains of those listed by the .I Domain parameter as well as the actual domains. .TP .I Syslog (Boolean) Log via calls to .I syslog(3) any interesting activity. .TP .I SyslogFacility (string) Log via calls to .I syslog(3) using the named facility. The facility names are the same as the ones allowed in .I syslog.conf(5). The default is "mail". .TP .I SyslogName (string) Log via calls to .I syslog(3) using that name. That way one could distinguish multiple instances. The default is the name of the executable, normally "opendkim". .TP .I SyslogSuccess (Boolean) Log via calls to .I syslog(3) additional entries indicating successful signing or verification of messages. .TP .I TemporaryDirectory (string) Specifies the directory in which temporary canonicalization files should be written. The default is to use the .I libopendkim default location, currently .I /tmp. .TP .I TestDNSData (data set) Provides a data set whose keys will be treated as DNS record names and values as TXT record contents. Intended for use during automated testing. .TP .I TestPublicKeys (string) Names a file from which public keys should be read. Intended for use only during automated testing. .TP .I TrustAnchorFile (string) Specifies a file from which trust anchor data should be read when doing DNS queries and applying the DNSSEC protocol. This is currently ignored unless the underlying library is compiled to use Unbound; see the documentation at at http://unbound.net for the expected format of this file. .TP .I TrustSignaturesFrom (dataset) This value consists of a set of domains that are considered trustworthy in terms of third-party signatures. That is, if a message arrives with a signature from a domain that doesn't match the domain in the From: header, this setting determines whether or not that signature will be trusted. If this value is undefined, all signatures are trusted. .TP .I UMask (integer) Requests a specific permissions mask to be used for file creation. This only really applies to creation of the socket when .I Socket specifies a UNIX domain socket, and to the .I PidFile (if any); temporary files are created by the .I mkstemp(3) function that enforces a specific file mode on creation regardless of the process umask. See .I umask(2) for more information. .TP .I UnprotectedKey (string) Instructs the filter to treat a passing signature associated with a key found in an insecure (i.e. not protected by DNSSEC) DNS record in a special way. Possible values are .I neutral (return a "neutral" result), .I none (take no special action; this is the default) and .I fail (return a "fail" result). @UNBOUND_MANNOTICE@ .TP .I UserID (string) Attempts to become the specified userid before starting operations. The value is of the form .I userid[:group]. The process will be assigned all of the groups and primary group ID of the named .I userid unless an alternate .I group is specified. .TP .I VBR-Certifiers (string) The default certifiers if not specified in X-VBR-Certifiers header field. @VBR_MANNOTICE@ .TP .I VBR-PurgeFields (string) If set, arranges to remove X-VBR-Certifiers and X-VBR-Type fields on messages prior to sending them. @VBR_MANNOTICE@ .TP .I VBR-TrustedCertifiers (string) A colon or comma sparated list of trusted certifiers to accept when verifying VBR-Info header field. @VBR_MANNOTICE@ .TP .I VBR-TrustedCertifiersOnly (Boolean) By default, the certifiers that are in both the trusted certifiers list (above) and those in the message's VBR-Info header field will be checked for vouching. With this option set, the trusted certifiers will be checked and the ones claimed by the message will be ignored. @VBR_MANNOTICE@ .TP .I VBR-Type (string) This default VBR type if not specified in the X-VBR-Type header field. @VBR_MANNOTICE@ .TP .I WeakSyntaxChecks (Boolean) Requests that the library continue processing messages even if syntax errors are discovered early in message analysis. This means, for example, that a signed message with a mangled From: field will still proceed to verification even if the author's domain could not be determined. .SH NOTES When using DNS timeouts (see the .I DNSTimeout option above), be sure not to use a timeout that is larger than the timeout being used for interaction between .I sendmail and the filter. Otherwise, the MTA could abort a message while waiting for a reply from the filter, which in turn is still waiting for a DNS reply. Features that involve specification of IPv4 addresses or CIDR blocks will use the .I inet_addr(3) function to parse that information. Users should be familiar with the way that function handles the non-trivial cases (for example, "192.0.2/24" and "192.0.2.0/24" are not the same thing). .SH FILES .TP .I @SYSCONFDIR@/opendkim.conf Default location of this file. .SH VERSION This man page covers version @VERSION@ of .I opendkim. .SH COPYRIGHT Copyright (c) 2007, 2008, Sendmail, Inc. and its suppliers. All rights reserved. Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), opendkim-lua(3), sendmail(8) .P RFC5451 - Message Header Field for Indicating Message Authentication Status .P RFC5617 - DKIM Author Domain Signing Practises .P RFC5965 - An Extensible Format for Email Feedback Reports .P RFC6008 - Authentication-Results Registration for Differentiating among Cryptographic Results .P RFC6376 - DomainKeys Identified Mail .P RFC6651 - Extensions to DomainKeys Identified Mail (DKIM) for Failure Reporting OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.conf.sample000066400000000000000000000527671337314105200242410ustar00rootroot00000000000000## ## opendkim.conf -- configuration file for OpenDKIM filter ## ## Copyright (c) 2010-2015, 2018, The Trusted Domain Project. ## All rights reserved. ## ## ## For settings that refer to a "dataset", see the opendkim(8) man page. ## ## DEPRECATED CONFIGURATION OPTIONS ## ## The following configuration options are no longer valid. They should be ## removed from your existing configuration file to prevent potential issues. ## Failure to do so may result in opendkim being unable to start. ## ## Removed in 2.10.0: ## AddAllSignatureResults ## ADSPAction ## ADSPNoSuchDomain ## BogusPolicy ## DisableADSP ## LDAPSoftStart ## LocalADSP ## NoDiscardableMailTo ## On-PolicyError ## SendADSPReports ## UnprotectedPolicy ## CONFIGURATION OPTIONS ## AllowSHA1Only { yes | no } ## default "no" ## ## By default, the filter will refuse to start if support for SHA256 is ## not available since this violates the strong recommendations of ## RFC6376 Section 3.3, which says: ## ## "Verifiers MUST implement both rsa-sha1 and rsa-sha256. Signers MUST ## implement and SHOULD sign using rsa-sha256." ## ## This forces that violation to be explicitly selected by the administrator. # AllowSHA1Only no ## AlwaysAddARHeader { yes | no } ## default "no" ## ## Add an "Authentication-Results:" header even to unsigned messages ## from domains with no "signs all" policy. The reported DKIM result ## will be "none" in such cases. Normally unsigned mail from non-strict ## domains does not cause the results header to be added. # AlwaysAddARHeader no ## AuthservID string ## default (local host name) ## ## Defines the "authserv-id" token to be used when generating ## Authentication-Results headers after message verification. # AuthservID example.com ## AuthservIDWithJobID ## default "no" ## ## Appends a "/" followed by the MTA's job ID to the "authserv-id" token ## when generating Authentication-Results headers after message verification. # AuthservIDWithJobId no ## AutoRestart { yes | no } ## default "no" ## ## Indicate whether or not the filter should arrange to restart automatically ## if it crashes. # AutoRestart No ## AutoRestartCount n ## default 0 ## ## Sets the maximum automatic restart count. After this number of ## automatic restarts, the filter will give up and terminate. A value of 0 ## implies no limit. # AutoRestartCount 0 ## AutoRestartRate n/t[u] ## default (none) ## ## Sets the maximum automatic restart rate. See the opendkim.conf(5) ## man page for the format of this parameter. # AutoRestartRate n/tu ## Background { yes | no } ## default "yes" ## ## Indicate whether or not the filter should run in the background. # Background Yes ## BaseDirectory path ## default (none) ## ## Causes the filter to change to the named directory before beginning ## operation. Thus, cores will be dumped here and configuration files ## are read relative to this location. # BaseDirectory /var/run/opendkim ## BodyLengthDB dataset ## default (none) ## ## A data set that is checked against envelope recipients to see if a ## body length tag should be included in the generated signature. ## This has security implications; see opendkim.conf(5) for details. # BodyLengthDB dataset ## Canonicalization hdrcanon[/bodycanon] ## default "simple/simple" ## ## Select canonicalizations to use when signing. If the "bodycanon" is ## omitted, "simple" is used. Valid values for each are "simple" and ## "relaxed". # Canonicalization simple/simple ## ClockDrift n ## default 300 ## ## Specify the tolerance range for expired signatures or signatures ## which appear to have timestamps in the future, allowing for clock ## drift. # ClockDrift 300 ## Diagnostics { yes | no } ## default "no" ## ## Specifies whether or not signatures with header diagnostic tags should ## be generated. # Diagnostics No ## DNSTimeout n ## default 10 ## ## Specify the time in seconds to wait for replies from the nameserver when ## requesting keys or signing policies. # DNSTimeout 10 ## Domain dataset ## default (none) ## ## Specify for which domain(s) signing should be done. No default; must ## be specified for signing. Domain example.com ## DomainKeysCompat { yes | no } ## default "no" ## ## When enabled, backward compatibility with DomainKeys (RFC4870) key ## records is enabled. Otherwise, such key records are considered to be ## syntactically invalid. # DomainKeysCompat no ## DontSignMailTo dataset ## default (none) ## ## Gives a list of recipient addresses or address patterns whose mail should ## not be signed. # DontSignMailTo addr1,addr2,... ## EnableCoredumps { yes | no } ## default "no" ## ## On systems which have support for such, requests that the kernel dump ## core even though the process may change user ID during its execution. # EnableCoredumps no ## ExemptDomains dataset ## default (none) ## ## A data set of domain names that are checked against the message sender's ## domain. If a match is found, the message is ignored by the filter. # ExemptDomains domain1,domain2,... ## ExternalIgnoreList filename ## ## Names a file from which a list of externally-trusted hosts is read. ## These are hosts which are allowed to send mail through you for signing. ## Automatically contains 127.0.0.1. See man page for file format. # ExternalIgnoreList filename ## FixCRLF { yes | no } ## ## Requests that the library convert "naked" CR and LF characters to ## CRLFs during canonicalization. The default is "no". # FixCRLF no ## IgnoreMalformedMail { yes | no } ## default "no" ## ## Silently passes malformed messages without alteration. This includes ## messages that fail the RequiredHeaders check, if enabled. The default is ## to pass those messages but add an Authentication-Results field indicating ## that they were malformed. # IgnoreMalformedMail no ## InternalHosts dataset ## default "127.0.0.1" ## ## Names a file from which a list of internal hosts is read. These are ## hosts from which mail should be signed rather than verified. ## Automatically contains 127.0.0.1. # InternalHosts dataset ## KeepTemporaryFiles { yes | no } ## default "no" ## ## If set, causes temporary files generated during message signing or ## verifying to be left behind for debugging use. Not for normal operation; ## can fill your disks quite fast on busy systems. # KeepTemporaryFiles no ## KeyFile filename ## default (none) ## ## Specifies the path to the private key to use when signing. Ignored if ## SigningTable and KeyTable are used. No default; must be specified for ## signing if SigningTable/KeyTable are not in use. KeyFile /var/db/dkim/example.private ## KeyTable dataset ## default (none) ## ## Defines a table that will be queried to convert key names to ## sets of data of the form (signing domain, signing selector, private key). ## The private key can either contain a PEM-formatted private key, ## a base64-encoded DER format private key, or a path to a file containing ## one of those. # KeyTable dataset ## LogWhy { yes | no } ## default "no" ## ## If logging is enabled (see Syslog below), issues very detailed logging ## about the logic behind the filter's decision to either sign a message ## or verify it. The logic behind the decision is non-trivial and can be ## confusing to administrators not familiar with its operation. A ## description of how the decision is made can be found in the OPERATIONS ## section of the opendkim(8) man page. This causes a large increase ## in the amount of log data generated for each message, so it should be ## limited to debugging use and not enabled for general operation. # LogWhy no ## MacroList macro[=value][,...] ## ## Gives a set of MTA-provided macros which should be checked to see ## if the sender has been determined to be a local user and therefore ## whether or not signing should be done. See opendkim.conf(5) for ## more information. # MacroList foo=bar,baz=blivit ## MaximumHeaders n ## ## Disallow messages whose header blocks are bigger than "n" bytes. ## Intended to detect and block a denial-of-service attack. The default ## is 65536. A value of 0 disables this test. # MaximumHeaders n ## MaximumSignaturesToVerify n ## (default 3) ## ## Verify no more than "n" signatures on an arriving message. ## A value of 0 means "no limit". # MaximumSignaturesToVerify n ## MaximumSignedBytes n ## ## Don't sign more than "n" bytes of the message. The default is to ## sign the entire message. Setting this implies "BodyLengths". # MaximumSignedBytes n ## MilterDebug n ## ## Request a debug level of "n" from the milter library. The default is 0. # MilterDebug 0 ## Minimum n[% | +] ## default 0 ## ## Sets a minimum signing volume; one of the following formats: ## n at least n bytes (or the whole message, whichever is less) ## must be signed ## n% at least n% of the message must be signed ## n+ if a length limit was presented in the signature, no more than ## n bytes may have been added # Minimum n ## MinimumKeyBits n ## default 1024 ## ## Causes the library not to accept signatures matching keys made of fewer ## than the specified number of bits, even if they would otherwise pass ## DKIM signing. # MinimumKeyBits 1024 ## Mode [sv] ## default sv ## ## Indicates which mode(s) of operation should be provided. "s" means ## "sign", "v" means "verify". # Mode sv ## MTA dataset ## default (none) ## ## Specifies a list of MTAs whos mail should always be signed rather than ## verified. The "mtaname" is extracted from the DaemonPortOptions line ## in effect. # MTA name ## MultipleSignatures { yes | no } ## default no ## ## Allows multiple signatures to be added. If set to "true" and a SigningTable ## is in use, all SigningTable entries that match the candidate message will ## cause a signature to be added. Otherwise, only the first matching ## SigningTable entry will be added, or only the key defined by Domain, ## Selector and KeyFile will be added. # MultipleSignatures no ## MustBeSigned dataset ## default (none) ## ## Defines a list of headers which, if present on a message, must be ## signed for the signature to be considered acceptable. # MustBeSigned header1,header2,... ## Nameservers addr1[,addr2[,...]] ## default (none) ## ## Provides a comma-separated list of IP addresses that are to be used when ## doing DNS queries to retrieve DKIM keys, VBR records, etc. ## These override any local defaults built in to the resolver in use, which ## may be defined in /etc/resolv.conf or hard-coded into the software. # Nameservers addr1,addr2,... ## NoHeaderB { yes | no } ## default "no" ## ## Suppresses addition of "header.b" tags on Authentication-Results ## header fields. # NoHeaderB no ## OmitHeaders dataset ## default (none) ## ## Specifies a list of headers that should always be omitted when signing. ## Header names should be separated by commas. # OmitHeaders header1,header2,... ## On-... ## ## Specifies what to do when certain error conditions are encountered. ## ## See opendkim.conf(5) for more information. # On-Default # On-BadSignature # On-DNSError # On-InternalError # On-NoSignature # On-Security # On-SignatureError ## OversignHeaders dataset ## default (none) ## ## Specifies a set of header fields that should be included in all signature ## header lists (the "h=" tag) once more than the number of times they were ## actually present in the signed message. See opendkim.conf(5) for more ## information. # OverSignHeaders header1,header2,... ## PeerList dataset ## default (none) ## ## Contains a list of IP addresses, CIDR blocks, hostnames or domain names ## whose mail should be neither signed nor verified by this filter. See man ## page for file format. # PeerList filename ## PidFile filename ## default (none) ## ## Name of the file where the filter should write its pid before beginning ## normal operations. # PidFile filename ## POPDBFile dataset ## default (none) ## ## Names a database which should be checked for "POP before SMTP" records ## as a form of authentication of users who may be sending mail through ## the MTA for signing. Requires special compilation of the filter. ## See opendkim.conf(5) for more information. # POPDBFile filename ## Quarantine { yes | no } ## default "no" ## ## Indicates whether or not the filter should arrange to quarantine mail ## which fails verification. Intended for diagnostic use only. # Quarantine No ## QueryCache { yes | no } ## default "no" ## ## Instructs the DKIM library to maintain its own local cache of keys and ## policies retrieved from DNS, rather than relying on the nameserver for ## caching service. Useful if the nameserver being used by the filter is ## not local. The filter must be compiled with the QUERY_CACHE flag to enable ## this feature, since it adds a library dependency. # QueryCache No ## RedirectFailuresTo address ## default (none) ## ## Redirects signed messages to the specified address if none of the ## signatures present failed to verify. # RedirectFailuresTo postmaster@example.com ## RemoveARAll { yes | no } ## default "no" ## ## Remove all Authentication-Results: headers on all arriving mail. # RemoveARAll No ## RemoveARFrom dataset ## default (none) ## ## Remove all Authentication-Results: headers on all arriving mail that ## claim to have been added by hosts listed in this parameter. The list ## should be comma-separated. Entire domains may be specified by preceding ## the dopmain name by a single dot (".") character. # RemoveARFrom host1,host2,.domain1,.domain2,... ## RemoveOldSignatures { yes | no } ## default "no" ## ## Remove old signatures on messages, if any, when generating a signature. # RemoveOldSignatures No ## ReportAddress addr ## default (executing user)@(hostname) ## ## Specifies the sending address to be used on From: headers of outgoing ## failure reports. By default, the e-mail address of the user executing ## the filter is used. # ReportAddress "DKIM Error Postmaster" ## ReportBccAddress addr ## default (none) ## ## Specifies additional recipient address(es) to receive outgoing failure ## reports. # ReportBccAddress postmaster@example.com, john@example.com ## RequiredHeaders { yes | no } ## default no ## ## Rejects messages which don't conform to RFC5322 header count requirements. # RequiredHeaders No ## RequireSafeKeys { yes | no } ## default yes ## ## Refuses to use key files that appear to have unsafe permissions. # RequireSafeKeys Yes ## ResignAll { yes | no } ## default no ## ## Where ResignMailTo triggers a re-signing action, this flag indicates ## whether or not all mail should be signed (if set) versus only verified ## mail being signed (if not set). # ResignAll No ## ResignMailTo dataset ## default (none) ## ## Checks each message recipient against the specified dataset for a ## matching record. The full address is checked in each case, then the ## hostname, then each domain preceded by ".". If there is a match, the ## value returned is presumed to be the name of a key in the KeyTable ## (if defined) to be used to re-sign the message in addition to ## verifying it. If there is a match without a KeyTable, the default key ## is applied. # ResignMailTo dataset ## ResolverConfiguration string ## ## Passes arbitrary configuration data to the resolver. For the stock UNIX ## resolver, this is ignored; for Unbound, it names a resolv.conf(5)-style ## file that should be read for configuration information. # ResolverConfiguration string ## ResolverTracing { yes | no } ## ## Requests enabling of resolver trace features, if available. The effect ## of setting this flag depends on how trace features, if any, are implemented ## in the resolver in use. Currently only effective when used with the ## OpenDKIM asynchronous resolver. # ResolverTracing no ## Selector name ## ## The name of the selector to use when signing. No default; must be ## specified for signing. Selector my-selector-name ## SenderHeaders dataset ## default (none) ## ## Overrides the default list of headers that will be used to determine ## the sending domain when deciding whether to sign the message and with ## with which key(s). See opendkim.conf(5) for details. # SenderHeaders From ## SendReports { yes | no } ## default "no" ## ## Specifies whether or not the filter should generate report mail back ## to senders when verification fails and an address for such a purpose ## is provided. See opendkim.conf(5) for details. # SendReports No ## SignatureAlgorithm signalg ## default "rsa-sha256" ## ## Signature algorithm to use when generating signatures. Must be one of ## "rsa-sha1", "rsa-sha256", or "ed25519-sha256". # SignatureAlgorithm rsa-sha256 ## SignatureTTL seconds ## default "0" ## ## Specifies the lifetime in seconds of signatures generated by the ## filter. A value of 0 means no expiration time is included in the ## signature. # SignatureTTL 0 ## SignHeaders dataset ## default (none) ## ## Specifies the list of headers which should be included when generating ## signatures. The string should be a comma-separated list of header names. ## See the opendkim.conf(5) man page for more information. # SignHeaders header1,header2,... ## SigningTable dataset ## default (none) ## ## Defines a dataset that will be queried for the message sender's address ## to determine which private key(s) (if any) should be used to sign the ## message. The sender is determined from the value of the sender ## header fields as described with SenderHeaders above. The key for this ## lookup should be an address or address pattern that matches senders; ## see the opendkim.conf(5) man page for more information. The value ## of the lookup should return the name of a key found in the KeyTable ## that should be used to sign the message. If MultipleSignatures ## is set, all possible lookup keys will be attempted which may result ## in multiple signatures being applied. # SigningTable filename ## SingleAuthResult { yes | no} ## default "no" ## ## When DomainKeys verification is enabled, multiple Authentication-Results ## will be added, one for DK and one for DKIM. With this enabled, only ## a DKIM result will be reported unless DKIM failed but DK passed, in which ## case only a DK result will be reported. # SingleAuthResult no ## SMTPURI uri ## ## Specifies a URI (e.g., "smtp://localhost") to which mail should be sent ## via SMTP when notifications are generated. # Socket smtp://localhost ## Socket socketspec ## ## Names the socket where this filter should listen for milter connections ## from the MTA. Required. Should be in one of these forms: ## ## inet:port@address to listen on a specific interface ## inet:port to listen on all interfaces ## local:/path/to/socket to listen on a UNIX domain socket Socket inet:port@localhost ## SoftwareHeader { yes | no } ## default "no" ## ## Add a DKIM-Filter header field to messages passing through this filter ## to identify messages it has processed. # SoftwareHeader no ## StrictHeaders { yes | no } ## default "no" ## ## Requests that the DKIM library refuse to process a message whose ## header fields do not conform to the standards, in particular Section 3.6 ## of RFC5322. # StrictHeaders no ## StrictTestMode { yes | no } ## default "no" ## ## Selects strict CRLF mode during testing (see the "-t" command line ## flag in the opendkim(8) man page). Messages for which all header ## fields and body lines are not CRLF-terminated are considered malformed ## and will produce an error. # StrictTestMode no ## SubDomains { yes | no } ## default "no" ## ## Sign for subdomains as well? # SubDomains No ## Syslog { yes | no } ## default "yes" ## ## Log informational and error activity to syslog? Syslog Yes ## SyslogFacility facility ## default "mail" ## ## Valid values are : ## auth cron daemon kern lpr mail news security syslog user uucp ## local0 local1 local2 local3 local4 local5 local6 local7 ## ## syslog facility to be used # SyslogFacility mail ## SyslogName ident ## default "opendkim" (or the name of the executable) ## ## Identifier to be prepended to all generated log entries. # SyslogName opendkim ## SyslogSuccess { yes | no } ## default "no" ## ## Log success activity to syslog? # SyslogSuccess No ## TemporaryDirectory path ## default /tmp ## ## Specifies which directory will be used for creating temporary files ## during message processing. # TemporaryDirectory /tmp ## TestPublicKeys filename ## default (none) ## ## Names a file from which public keys should be read. Intended for use ## only during automated testing. # TestPublicKeys /tmp/testkeys ## TrustAnchorFile filename ## default (none) ## ## Specifies a file from which trust anchor data should be read when doing ## DNS queries and applying the DNSSEC protocol. See the Unbound documentation ## at http://unbound.net for the expected format of this file. # TrustAnchorFile /var/named/trustanchor ## UMask mask ## default (none) ## ## Change the process umask for file creation to the specified value. ## The system has its own default which will be used (usually 022). ## See the umask(2) man page for more information. # UMask 022 # UnboundConfigFile /var/named/unbound.conf ## Userid userid ## default (none) ## ## Change to user "userid" before starting normal operation? May include ## a group ID as well, separated from the userid by a colon. # UserID userid OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.conf.simple-verify.in000066400000000000000000000006601337314105200261410ustar00rootroot00000000000000 # This is a simple config file verifying messages only #LogWhy yes Syslog yes SyslogSuccess yes Socket inet:8891@localhost ReportAddress postmaster@@DOMAIN@ SendReports yes Mode v ## For secondary mailservers - indicates not to verify message from these hosts # PeerList X.X.X.X # ADSPDiscard no # PidFile /var/run/opendkim/opendkim.pid OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.conf.simple.in000066400000000000000000000013011337314105200246300ustar00rootroot00000000000000# This is a simple config file for signing and verifying #LogWhy yes Syslog yes SyslogSuccess yes Canonicalization relaxed/simple Domain @DOMAIN@ Selector default KeyFile /var/db/dkim/@DOMAIN@.private Socket inet:8891@localhost ReportAddress postmaster@@DOMAIN@ SendReports yes ## Hosts to sign email for - 127.0.0.1 is default ## See the OPERATION section of opendkim(8) for more information # # InternalHosts 192.168.0.0/16, 10.0.0.0/8, 172.16.0.0/12 ## For secondary mailservers - indicates not to sign or verify messages ## from these hosts # # PeerList X.X.X.X # PidFile /var/run/opendkim/opendkim.pid OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/opendkim.h000066400000000000000000000143221337314105200222440ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved. */ #ifndef _OPENDKIM_H_ #define _OPENDKIM_H_ #define DKIMF_PRODUCT "OpenDKIM Filter" #define DKIMF_PRODUCTNS "OpenDKIM-Filter" #include "build-config.h" /* system includes */ #include #ifdef HAVE_STDBOOL_H # include #endif /* HAVE_STDBOOL_H */ /* libmilter */ #ifdef DKIMF_MILTER_PROTOTYPES # include #endif /* DKIMF_MILTER_PROTOTYPES */ /* libopendkim */ #include "dkim.h" #ifdef USE_LUA # ifdef DKIMF_LUA_PROTOTYPES /* LUA */ # include # endif /* DKIMF_LUA_PROTOTYPES */ #endif /* USE_LUA */ /* make sure we have TRUE and FALSE */ #ifndef FALSE # define FALSE 0 #endif /* !FALSE */ #ifndef TRUE # define TRUE 1 #endif /* !TRUE */ /* defaults, limits, etc. */ #define BUFRSZ 1024 #define CACHESTATSINT 300 #define CBINTERVAL 3 #define DEFCONFFILE CONFIG_BASE "/opendkim.conf" #define DEFFLOWDATATTL 86400 #define DEFINTERNAL "csl:127.0.0.1,::1" #define DEFMAXHDRSZ 65536 #define DEFMAXVERIFY 3 #define DEFTIMEOUT 5 #define HOSTUNKNOWN "unknown-host" #define JOBIDUNKNOWN "(unknown-jobid)" #define LOCALHOST "127.0.0.1" #define MAXADDRESS 256 #define MAXARGV 65536 #define MAXBUFRSZ 65536 #define MAXHDRCNT 64 #define MAXHDRLEN 78 #define MAXSIGNATURE 1024 #define MTAMARGIN 78 #define NULLDOMAIN "(invalid)" #define SUPERUSER "root" #define UNKNOWN "unknown" #define DB_DOMAINS 1 #define DB_THIRDPARTY 2 #define DB_DONTSIGNTO 3 #define DB_MTAS 4 #define DB_MACROS 5 #define DB_SIGNINGTABLE 6 #define AUTHRESULTSHDR "Authentication-Results" #define ORCPTHEADER "Original-Recipient" #define SWHEADERNAME "DKIM-Filter" #define SELECTCANONHDR "Canonicalization" #ifdef _FFR_VBR # define VBRTYPEHEADER "VBR-Type" # define VBRCERTHEADER "VBR-Certifiers" #endif /* _FFR_VBR */ #ifdef _FFR_ADSP_LISTS # define ADSP_DISCARDABLE_SMTP "550" # define ADSP_DISCARDABLE_ESC "5.7.1" # define ADSP_DISCARDABLE_TEXT "ADSP discardable mail may not be sent to this address" #endif /* _FFR_ADSP_LISTS */ /* POPAUTH db */ #if POPAUTH # define POPAUTHDB "/etc/mail/popip.db" #endif /* POPAUTH */ /* ** HEADER -- a handle referring to a header */ typedef struct Header * Header; struct Header { char * hdr_hdr; char * hdr_val; struct Header * hdr_next; struct Header * hdr_prev; }; /* ** SIGNREQ -- signing request (for multiple signature requests) */ typedef struct signreq * SIGNREQ; struct signreq { ssize_t srq_signlen; void * srq_keydata; u_char * srq_domain; u_char * srq_selector; u_char * srq_signer; DKIM * srq_dkim; struct signreq * srq_next; }; #ifdef _FFR_STATSEXT /* ** STATSEXT -- statistics extension data */ typedef struct statsext * statsext; struct statsext { char se_name[BUFRSZ]; char se_value[BUFRSZ]; struct statsext * se_next; }; #endif /* _FFR_STATSEXT */ /* externs */ extern _Bool dolog; extern char *progname; /* prototypes, exported for test.c */ #ifdef DKIMF_MILTER_PROTOTYPES extern sfsistat mlfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *)); extern sfsistat mlfi_envfrom __P((SMFICTX *, char **)); extern sfsistat mlfi_envrcpt __P((SMFICTX *, char **)); extern sfsistat mlfi_header __P((SMFICTX *, char *, char *)); extern sfsistat mlfi_eoh __P((SMFICTX *)); extern sfsistat mlfi_body __P((SMFICTX *, u_char *, size_t)); extern sfsistat mlfi_eom __P((SMFICTX *)); extern sfsistat mlfi_abort __P((SMFICTX *)); extern sfsistat mlfi_close __P((SMFICTX *)); #endif /* DKIMF_MILTER_PROTOTYPES */ extern DKIM *dkimf_getdkim __P((void *)); extern struct signreq *dkimf_getsrlist __P((void *)); #ifdef USE_LDAP extern char *dkimf_get_ldap_param __P((int)); #endif /* USE_LDAP */ #ifdef USE_LUA # ifdef DKIMF_LUA_PROTOTYPES extern void dkimf_import_globals __P((void *, lua_State *)); extern int dkimf_xs_addheader __P((lua_State *)); extern int dkimf_xs_addrcpt __P((lua_State *)); extern int dkimf_xs_bodylength __P((lua_State *)); extern int dkimf_xs_canonlength __P((lua_State *)); extern int dkimf_xs_clienthost __P((lua_State *)); extern int dkimf_xs_clientip __P((lua_State *)); extern int dkimf_xs_dbclose __P((lua_State *)); extern int dkimf_xs_dbhandle __P((lua_State *)); extern int dkimf_xs_dbopen __P((lua_State *)); extern int dkimf_xs_dbquery __P((lua_State *)); extern int dkimf_xs_delheader __P((lua_State *)); extern int dkimf_xs_delrcpt __P((lua_State *)); extern int dkimf_xs_export __P((lua_State *)); extern int dkimf_xs_fromdomain __P((lua_State *)); extern int dkimf_xs_getenvfrom __P((lua_State *)); extern int dkimf_xs_getheader __P((lua_State *)); extern int dkimf_xs_getreputation __P((lua_State *)); extern int dkimf_xs_getsigarray __P((lua_State *)); extern int dkimf_xs_getsigcount __P((lua_State *)); extern int dkimf_xs_getsigdomain __P((lua_State *)); extern int dkimf_xs_getsighandle __P((lua_State *)); extern int dkimf_xs_getsigidentity __P((lua_State *)); extern int dkimf_xs_getsymval __P((lua_State *)); extern int dkimf_xs_internalip __P((lua_State *)); extern int dkimf_xs_log __P((lua_State *)); extern int dkimf_xs_parsefield __P((lua_State *)); extern int dkimf_xs_popauth __P((lua_State *)); extern int dkimf_xs_quarantine __P((lua_State *)); extern int dkimf_xs_rblcheck __P((lua_State *)); extern int dkimf_xs_rcpt __P((lua_State *)); extern int dkimf_xs_rcptarray __P((lua_State *)); extern int dkimf_xs_rcptcount __P((lua_State *)); extern int dkimf_xs_replaceheader __P((lua_State *)); extern int dkimf_xs_resign __P((lua_State *)); extern int dkimf_xs_requestsig __P((lua_State *)); extern int dkimf_xs_setpartial __P((lua_State *)); extern int dkimf_xs_setreply __P((lua_State *)); extern int dkimf_xs_setresult __P((lua_State *)); extern int dkimf_xs_sigbhresult __P((lua_State *)); extern int dkimf_xs_sigignore __P((lua_State *)); extern int dkimf_xs_signfor __P((lua_State *)); extern int dkimf_xs_sigresult __P((lua_State *)); # ifdef _FFR_REPUTATION extern int dkimf_xs_spam __P((lua_State *)); # endif /* _FFR_REPUTATION */ # ifdef _FFR_STATSEXT extern int dkimf_xs_statsext __P((lua_State *)); # endif /* _FFR_STATSEXT */ extern int dkimf_xs_verify __P((lua_State *)); extern int dkimf_xs_xtag __P((lua_State *)); # endif /* DKIMF_LUA_PROTOTYPES */ #endif /* USE_LUA */ #endif /* _OPENDKIM_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/reputation.c000066400000000000000000000333271337314105200226310ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2011-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" #ifdef _FFR_REPUTATION /* system includes */ #include #include #include #include #include #include #include /* libopendkim includes */ #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "reputation.h" #include "opendkim.h" #include "opendkim-db.h" /* macros */ #define DKIMF_REP_DEFCACHE "db:" #define DKIMF_REP_MAXHASHES 64 #define DKIMF_REP_NULLDOMAIN "UNSIGNED" #define DKIMF_REP_LOWTIME "LOW-TIME" /* data types */ struct reputation { time_t rep_ttl; time_t rep_lastflush; unsigned int rep_factor; unsigned int rep_minimum; DKIMF_DB rep_reps; DKIMF_DB rep_dups; DKIMF_DB rep_limits; DKIMF_DB rep_limitmods; DKIMF_DB rep_ratios; DKIMF_DB rep_counts; DKIMF_DB rep_spam; DKIMF_DB rep_lowtime; pthread_mutex_t rep_lock; }; struct reps { time_t reps_retrieved; unsigned long reps_count; unsigned long reps_limit; unsigned long reps_spam; float reps_ratio; }; /* ** DKIMF_REP_INIT -- initialize reputation ** ** Parameters: ** rep -- reputation DB query handle (returned) ** factor -- number of slices in a reputation limit ** minimum -- always accept at least this many messages ** cachettl -- TTL for cache entries ** cache -- data set to which to cache ** dups -- data set to which to record duplicates ** limits -- DB from which to get per-domain limits ** limitmods -- DB from which to get per-domain limit modifiers ** ratios -- DB from which to get per-domain ratios ** lowtime -- DB from which to check for low-time domain status ** ** Return value: ** 0 on success, -1 on error. */ int dkimf_rep_init(DKIMF_REP *rep, time_t factor, unsigned int minimum, unsigned int cachettl, char *cache, char *dups, DKIMF_DB limits, DKIMF_DB limitmods, DKIMF_DB ratios, DKIMF_DB lowtime) { int status; DKIMF_REP new; assert(rep != NULL); assert(ratios != NULL); assert(factor != 0); new = malloc(sizeof *new); if (new == NULL) return -1; #ifdef USE_MDB if (cache == NULL || dups == NULL) return -1; #else /* USE_MDB */ if (cache == NULL) cache = DKIMF_REP_DEFCACHE; if (dups == NULL) dups = DKIMF_REP_DEFCACHE; #endif /* USE_MDB */ new->rep_lastflush = time(NULL); new->rep_ttl = cachettl; new->rep_factor = factor; new->rep_limits = limits; new->rep_limitmods = limitmods; new->rep_ratios = ratios; new->rep_lowtime = lowtime; new->rep_minimum = minimum; if (pthread_mutex_init(&new->rep_lock, NULL) != 0) { free(new); return -1; } status = dkimf_db_open(&new->rep_reps, cache, 0, NULL, NULL); if (status != 0) { free(new); return -1; } status = dkimf_db_open(&new->rep_dups, dups, 0, NULL, NULL); if (status != 0) { dkimf_db_close(new->rep_reps); free(new); return -1; } *rep = new; return 0; } /* ** DKIMF_REP_CLOSE -- shut down reputation ** ** Parameters: ** rephandle -- reputation DB query handle ** ** Return value: ** None. */ void dkimf_rep_close(DKIMF_REP rephandle) { assert(rephandle != NULL); (void) dkimf_db_close(rephandle->rep_reps); (void) dkimf_db_close(rephandle->rep_dups); (void) pthread_mutex_destroy(&rephandle->rep_lock); } /* ** DKIMF_REP_CHECK -- check reputation ** ** Parameters: ** rep -- reputation service handle ** sig -- a valid signature on this message ** spam -- spammy or not spammy? That is the question. ** hash -- hash of the message, for counting dups ** hashlen -- number of bytes in the hash ** limit -- limit for this signer (returned) ** ratio -- spam ratio for this signer (returned) ** count -- message count for this signer (returned) ** spamcnt -- spam count for this signer (returned) ** errbuf -- buffer to receive errors ** errlen -- bytes available at errbuf ** ** Return value: ** 2 -- no data found for this domain ** 1 -- deny the request ** 0 -- allow the request ** -1 -- error ** ** Notes: ** If "sig" is NULL, the null domain record is queried. */ int dkimf_rep_check(DKIMF_REP rep, DKIM_SIGINFO *sig, _Bool spam, void *hash, size_t hashlen, unsigned long *limit, float *ratio, unsigned long *count, unsigned long *spamcnt, char *errbuf, size_t errlen) { _Bool f; size_t dlen; size_t hlen; time_t when; time_t now; struct dkimf_db_data req[5]; struct reps reps; char buf[BUFRSZ + 1]; char domain[DKIM_MAXHOSTNAMELEN + 1]; unsigned char hashbuf[DKIMF_REP_MAXHASHES]; assert(rep != NULL); (void) time(&now); pthread_mutex_lock(&rep->rep_lock); /* flush the caches if needed */ if (rep->rep_lastflush + rep->rep_ttl < now) { f = TRUE; req[0].dbdata_buffer = (void *) &when; req[0].dbdata_buflen = sizeof when; req[0].dbdata_flags = DKIMF_DB_DATA_BINARY; hlen = sizeof hashbuf; while (dkimf_db_walk(rep->rep_dups, f, hashbuf, &hlen, req, 1) == 0) { if (when + rep->rep_ttl < now) { (void) dkimf_db_delete(rep->rep_dups, hashbuf, hlen); } req[0].dbdata_buffer = (void *) &when; req[0].dbdata_buflen = sizeof when; req[0].dbdata_flags = DKIMF_DB_DATA_BINARY; f = FALSE; hlen = sizeof hashbuf; } req[0].dbdata_buffer = (void *) &reps; req[0].dbdata_buflen = sizeof reps; req[0].dbdata_flags = DKIMF_DB_DATA_BINARY; f = TRUE; hlen = sizeof domain; memset(domain, '\0', sizeof domain); while (dkimf_db_walk(rep->rep_reps, f, domain, &hlen, req, 1) == 0) { if (reps.reps_retrieved + rep->rep_ttl < now) { (void) dkimf_db_delete(rep->rep_reps, domain, hlen); } req[0].dbdata_buffer = (void *) &reps; req[0].dbdata_buflen = sizeof reps; req[0].dbdata_flags = DKIMF_DB_DATA_BINARY; f = FALSE; hlen = sizeof domain; memset(domain, '\0', sizeof domain); } rep->rep_lastflush = now; } /* get the ratio and limit for this domain */ req[0].dbdata_buffer = (void *) &reps; req[0].dbdata_buflen = sizeof reps; req[0].dbdata_flags = DKIMF_DB_DATA_BINARY; if (sig == NULL) strlcpy(domain, DKIMF_REP_NULLDOMAIN, sizeof domain); else strlcpy(domain, dkim_sig_getdomain(sig), sizeof domain); dlen = strlen(domain); /* check cache first */ f = FALSE; if (dkimf_db_get(rep->rep_reps, domain, dlen, req, 1, &f) != 0) { if (errbuf != NULL) dkimf_db_strerror(rep->rep_reps, errbuf, errlen); pthread_mutex_unlock(&rep->rep_lock); return -1; } if (!f) { _Bool lowtime = FALSE; char *p = NULL; /* cache miss; build a new cache entry */ reps.reps_count = 0; reps.reps_limit = ULONG_MAX; reps.reps_spam = 0; reps.reps_retrieved = time(NULL); req[0].dbdata_buffer = buf; req[0].dbdata_buflen = sizeof buf; req[0].dbdata_flags = 0; if (rep->rep_lowtime != NULL) { /* see if it's a low-time domain */ if (dkimf_db_get(rep->rep_lowtime, domain, dlen, req, 1, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } if (f) lowtime = (atoi(buf) != 0); memset(buf, '\0', sizeof buf); req[0].dbdata_buffer = buf; req[0].dbdata_buflen = sizeof buf; req[0].dbdata_flags = 0; } if (lowtime) { strlcpy(domain, DKIMF_REP_LOWTIME, sizeof domain); dlen = strlen(domain); } f = FALSE; /* get the total message limit */ if (rep->rep_limits != NULL) { int fields = 1; if (dkimf_db_type(rep->rep_limits) == DKIMF_DB_TYPE_REPUTE) fields = 5; memset(req, '\0', sizeof req); req[fields - 1].dbdata_buffer = buf; req[fields - 1].dbdata_buflen = sizeof buf; req[fields - 1].dbdata_flags = 0; if (dkimf_db_get(rep->rep_limits, domain, dlen, req, fields, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } if (!f && !lowtime && sig != NULL) { if (dkimf_db_get(rep->rep_limits, DKIMF_REP_LOWTIME, strlen(DKIMF_REP_LOWTIME), req, fields, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } } if (!f) { if (dkimf_db_get(rep->rep_limits, "*", 1, req, fields, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } } if (!f || req[fields - 1].dbdata_buflen >= sizeof buf) { pthread_mutex_unlock(&rep->rep_lock); return 2; } buf[req[fields - 1].dbdata_buflen] = '\0'; reps.reps_limit = (unsigned long) (ceil((double) strtoul(buf, &p, 10) / (double) rep->rep_factor) + 1.); if (p != NULL && *p != '\0') { if (errbuf != NULL) { snprintf(errbuf, errlen, "failed to parse limit reply"); } pthread_mutex_unlock(&rep->rep_lock); return -1; } if (rep->rep_limitmods != NULL) { f = FALSE; req[0].dbdata_buffer = buf; req[0].dbdata_buflen = sizeof buf; req[0].dbdata_flags = 0; if (dkimf_db_get(rep->rep_limitmods, domain, dlen, req, 1, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } if (f && req[0].dbdata_buflen < sizeof buf) { unsigned int mod = 0; buf[req[0].dbdata_buflen] = '\0'; mod = strtoul(&buf[1], &p, 10); if (*p != '\0') buf[0] = '\0'; switch (buf[0]) { case '+': reps.reps_limit += mod; break; case '*': reps.reps_limit *= mod; break; case '-': reps.reps_limit -= mod; break; case '/': if (mod != 0) reps.reps_limit /= mod; break; case '=': reps.reps_limit = mod; break; } } } } /* get the spam ratio */ req[0].dbdata_buffer = buf; req[0].dbdata_buflen = sizeof buf; req[0].dbdata_flags = 0; f = FALSE; if (dkimf_db_get(rep->rep_ratios, domain, dlen, req, 1, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } if (!f && !lowtime && sig != NULL) { if (dkimf_db_get(rep->rep_ratios, DKIMF_REP_LOWTIME, strlen(DKIMF_REP_LOWTIME), req, 1, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } } if (!f) { if (dkimf_db_get(rep->rep_ratios, "*", 1, req, 1, &f) != 0) { if (errbuf != NULL) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); } pthread_mutex_unlock(&rep->rep_lock); return -1; } } if (!f || req[0].dbdata_buflen >= sizeof buf) { pthread_mutex_unlock(&rep->rep_lock); return 2; } buf[req[0].dbdata_buflen] = '\0'; p = NULL; reps.reps_ratio = strtof(buf, &p); if (p != NULL && *p != '\0') { if (errbuf != NULL) { snprintf(errbuf, errlen, "failed to parse ratio reply"); } pthread_mutex_unlock(&rep->rep_lock); return -1; } } req[0].dbdata_buffer = (void *) &when; req[0].dbdata_buflen = sizeof when; req[0].dbdata_flags = DKIMF_DB_DATA_BINARY; f = FALSE; if (dkimf_db_get(rep->rep_dups, hash, hashlen, req, 1, &f) != 0) { if (errbuf != NULL) dkimf_db_strerror(rep->rep_reps, errbuf, errlen); pthread_mutex_unlock(&rep->rep_lock); return -1; } /* up the counts if this is new */ if (!f) { reps.reps_count++; if (spam) reps.reps_spam++; /* write it to the cache */ if (dkimf_db_put(rep->rep_reps, domain, dlen, &reps, sizeof reps) != 0) { dkimf_db_strerror(rep->rep_reps, errbuf, errlen); pthread_mutex_unlock(&rep->rep_lock); return -1; } } /* export requested stats */ if (limit != NULL) *limit = reps.reps_limit; if (ratio != NULL) *ratio = reps.reps_ratio; if (count != NULL) *count = reps.reps_count; if (spamcnt != NULL) *spamcnt = reps.reps_spam; /* if accepting it now would be within limits */ if (reps.reps_count <= rep->rep_minimum || (reps.reps_count <= reps.reps_limit && (float) reps.reps_spam / (float) reps.reps_count <= reps.reps_ratio)) { /* remove from rep_dups if found there */ (void) dkimf_db_delete(rep->rep_dups, hash, hashlen); pthread_mutex_unlock(&rep->rep_lock); return 0; } else { /* record the dup */ (void) dkimf_db_put(rep->rep_dups, hash, hashlen, &now, sizeof now); pthread_mutex_unlock(&rep->rep_lock); return 1; } } /* ** DKIMF_REP_CHOWN_CACHE -- set the owner of a cache file ** ** Parameters: ** rep -- reputation handle ** uid -- target UID ** ** Return value: ** 0 -- success ** -1 -- failure */ int dkimf_rep_chown_cache(DKIMF_REP rep, uid_t uid) { assert(rep != NULL); assert(uid >= 0); if (dkimf_db_chown(rep->rep_reps, uid) == 1) return 0; else return -1; } #endif /* _FFR_REPUTATION */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/reputation.h000066400000000000000000000021501337314105200226240ustar00rootroot00000000000000/* ** Copyright (c) 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. ** */ #ifndef _REPUTATION_H_ #define _REPUTATION_H_ /* system includes */ #include #include /* opendkim includes */ #include "opendkim.h" #include "opendkim-db.h" /* definitions */ #define DKIMF_REP_DEFCACHETTL 3600 #define DKIMF_REP_DEFFACTOR 1 /* data types */ struct reputation; typedef struct reputation * DKIMF_REP; /* PROTOTYPES */ extern int dkimf_rep_init __P((DKIMF_REP *, time_t, unsigned int, unsigned int, char *, char *, DKIMF_DB, DKIMF_DB, DKIMF_DB, DKIMF_DB)); extern int dkimf_rep_check __P((DKIMF_REP, DKIM_SIGINFO *, _Bool, void *, size_t, unsigned long *, float *, unsigned long *, unsigned long *, char *, size_t)); extern int dkimf_rep_chown_cache __P((DKIMF_REP, uid_t)); extern void dkimf_rep_close __P((DKIMF_REP)); #endif /* _REPUTATION_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/screen.lua.sample000066400000000000000000000017301337314105200235260ustar00rootroot00000000000000-- -- Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. -- All rights reserved. -- -- screen.lua.sample -- sample version of the "screen" script that demonstrates -- all of the features of the configuration file -- -- The screen script is executed after all header fields have been received -- and after signatures have been selected, but before the message body -- is handled. Here we have an opportunity to identify and ignore signatures -- we know we don't trust. -- retrieve the count of signatures on the message nsigs = odkim.get_sigcount(ctx) if nsigs == nil then return nil end -- get the From: domain fdomain = odkim.get_fromdomain(ctx) if fdomain == nil then return nil end -- for each signature, ignore it if it's not from the sender's domain for n = 1, nsigs do sig = odkim.get_signhandle(ctx, n) sdomain = odkim.sig_getdomain(sig) if fdomain ~= sdomain then odkim.sig_ignore(sig) end end -- That's it! return nil OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/setup.lua.sample000066400000000000000000000042531337314105200234120ustar00rootroot00000000000000-- -- Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. -- All rights reserved. -- -- setup.lua.sample -- sample version of the "setup" script that demonstrates -- all of the features of the configuration file -- -- The setup script is executed after all header fields have been received -- but before any DKIM operations have begun. Thus, this script can decide -- what signatures, if any, should be added. -- We never sign mail to example.net nrcpts = odkim.rcpt_count(ctx) for n = 1, nrcpts do rcpt = odkim.get_rcpt(ctx, n - 1) if string.find(rcpt, "@example.net", 1, true) ~= nil then odkim.verify(ctx) return nil end end -- We blindly accept mail that looks like it's from example.org from = odkim.get_fromdomain(ctx) if from == "example.org" then odkim.set_result(ctx, SMFIS_ACCEPT) return nil end -- If POP-before-SMTP failed, just verify it popauth = odkim.check_popauth(ctx) if popauth == 0 then odkim.verify(ctx) return nil end -- See if {auth_author} was set author = odkim.get_mtasymbol(ctx, "{auth_author}") -- If it's not from an internal source or authenticated, just verify it if odkim.internal_ip(ctx) == 0 and author == nil then odkim.verify(ctx) return nil end -- If MTA name tests were requested, do the test and just verify if no match mtadb = odkim.get_dbhandle(ctx, DB_MTAS) if mtadb ~= nil then mtaname = odkim.get_mtasymbol(ctx, "{daemon_name}") if mtaname ~= nil then if odkim.db_check(mtadb, mtaname) == 0 then odkim.verify(ctx) return nil end end end -- Compare "From" domain to domains DB, just verify if no match domains = odkim.get_dbhandle(ctx, DB_DOMAINS) if domains == nil or odkim.db_check(domains, from) == 0 then odkim.verify(ctx) return nil end -- Since we got this far, we're signing; make a signing request using the -- key "defkey" odkim.sign(ctx, "defkey") -- If it looks like it might be going to a list (in that the recipient ends -- in "-l"), add an "l=" tag. (We need to add a hook for the body length -- DB, perhaps.) for n = 1, nrcpts do rcpt = odkim.get_rcpt(ctx, n - 1) if string.find(rcpt, "-l@", 1, true) ~= nil then odkim.use_ltag(ctx) end end -- That's it! return nil OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/stats.c000066400000000000000000000123411337314105200215660ustar00rootroot00000000000000/* ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" #ifdef _FFR_STATS /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef USE_GNUTLS /* GnuTLS includes */ # include # include # ifndef MD5_DIGEST_LENGTH # define MD5_DIGEST_LENGTH 16 # endif /* ! MD5_DIGEST_LENGTH */ #else /* USE_GNUTLS */ /* libcrypto includes */ # include #endif /* USE_GNUTLS */ /* libopendkim includes */ #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "stats.h" #include "util.h" #include "opendkim.h" #include "opendkim-db.h" /* globals */ static pthread_mutex_t stats_lock; /* ** DKIMF_STATS_INIT -- initialize statistics ** ** Parameters: ** None. ** ** Return value: ** None. */ void dkimf_stats_init(void) { pthread_mutex_init(&stats_lock, NULL); } /* ** DKIMF_STATS_RECORD -- record a DKIM result ** ** Parameters: ** path -- path to the DB to update ** jobid -- job ID for the current message ** name -- reporter name to record ** prefix -- hashing prefix ** hdrlist -- list of headers on the message ** dkimv -- verifying handle from which data can be taken ** sa -- client socket information ** ** Return value: ** 0 on success, !0 on failure */ int dkimf_stats_record(char *path, u_char *jobid, char *name, char *prefix, Header hdrlist, DKIM *dkimv, #ifdef _FFR_STATSEXT struct statsext *se, #endif /* _FFR_STATSEXT */ int atps, int spam, struct sockaddr *sa) { int status = 0; int nsigs = 0; int err; int c; ssize_t canonlen; ssize_t signlen; ssize_t msglen; FILE *out; unsigned char *from; char *p; DKIM_SIGINFO **sigs; char tmp[BUFRSZ + 1]; assert(path != NULL); assert(jobid != NULL); assert(name != NULL); pthread_mutex_lock(&stats_lock); /* open the log file */ out = fopen(path, "a"); if (out == NULL) { if (dolog) { syslog(LOG_ERR, "%s: fopen(): %s", path, strerror(errno)); } pthread_mutex_unlock(&stats_lock); return -1; } /* write version if file is new */ if (ftell(out) == 0) fprintf(out, "V%d\n", DKIMS_VERSION); /* write info */ status = dkim_getsiglist(dkimv, &sigs, &nsigs); if (status != DKIM_STAT_OK) { if (dolog) syslog(LOG_ERR, "%s: dkim_getsiglist() failed", jobid); fclose(out); pthread_mutex_unlock(&stats_lock); return 0; } from = dkim_getdomain(dkimv); if (from == NULL) { if (dolog) syslog(LOG_ERR, "%s: dkim_getdomain() failed", jobid); fclose(out); pthread_mutex_unlock(&stats_lock); return 0; } fprintf(out, "M%s\t%s\t%s", jobid, name, (char *) from); memset(tmp, '\0', sizeof tmp); switch (sa->sa_family) { case AF_INET: { struct sockaddr_in sin4; memcpy(&sin4, sa, sizeof sin4); (void) inet_ntop(AF_INET, &sin4.sin_addr, tmp, sizeof tmp); break; } #ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 sin6; memcpy(&sin6, sa, sizeof sin6); (void) inet_ntop(AF_INET6, &sin6.sin6_addr, tmp, sizeof tmp); break; } #endif /* AF_INET6 */ } if (tmp[0] == '\0') fprintf(out, "\tunknown"); else fprintf(out, "\t%s", tmp); fprintf(out, "\t%lu", time(NULL)); msglen = 0; canonlen = 0; signlen = 0; if (nsigs > 0) { (void) dkim_sig_getcanonlen(dkimv, sigs[0], &msglen, &canonlen, &signlen); } fprintf(out, "\t%lu", (unsigned long) canonlen); fprintf(out, "\t%d", nsigs); #ifdef _FFR_ATPS fprintf(out, "\t%d", atps); #else /* _FFR_ATPS */ fprintf(out, "\t-1"); #endif /* _FFR_ATPS */ #ifdef _FFR_REPUTATION fprintf(out, "\t%d", spam); #else /* _FFR_REPUTATION */ fprintf(out, "\t-1"); #endif /* _FFR_REPUTATION */ fprintf(out, "\n"); for (c = 0; c < nsigs; c++) { if ((dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_IGNORE) != 0) continue; fprintf(out, "S"); p = (char *) dkim_sig_getdomain(sigs[c]); fprintf(out, "%s", p); fprintf(out, "\t%d", (dkim_sig_getflags(sigs[c]) & DKIM_SIGFLAG_PASSED) != 0); fprintf(out, "\t%d", dkim_sig_getbh(sigs[c]) == DKIM_SIGBH_MISMATCH); (void) dkim_sig_getcanonlen(dkimv, sigs[c], &msglen, &canonlen, &signlen); fprintf(out, "\t%ld", (long) signlen); err = dkim_sig_geterror(sigs[c]); /* syntax error codes */ fprintf(out, "\t%d", err); fprintf(out, "\t%d", dkim_sig_getdnssec(sigs[c])); fprintf(out, "\n"); } #ifdef _FFR_STATSEXT if (se != NULL) { struct statsext *cur; for (cur = se; cur != NULL; cur = cur->se_next) fprintf(out, "X%s\t%s\n", cur->se_name, cur->se_value); } #endif /* _FFR_STATSEXT */ /* close output */ fclose(out); pthread_mutex_unlock(&stats_lock); return 0; } #endif /* _FFR_STATS */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/stats.h000066400000000000000000000023701337314105200215740ustar00rootroot00000000000000/* ** Copyright (c) 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. ** */ #ifndef _STATS_H_ #define _STATS_H_ /* system includes */ #include #include #include /* libopendkim includes */ #include /* opendkim includes */ #include "opendkim.h" #define DKIMS_VERSION 3 /* column numbers */ #define DKIMS_MI_JOBID 0 #define DKIMS_MI_REPORTER 1 #define DKIMS_MI_FROMDOMAIN 2 #define DKIMS_MI_IPADDR 3 #define DKIMS_MI_MSGTIME 4 #define DKIMS_MI_MSGLEN 5 #define DKIMS_MI_SIGCOUNT 6 #define DKIMS_MI_ATPS 7 #define DKIMS_MI_SPAM 8 #define DKIMS_MI_MAX 8 #define DKIMS_SI_DOMAIN 0 #define DKIMS_SI_PASS 1 #define DKIMS_SI_FAIL_BODY 2 #define DKIMS_SI_SIGLENGTH 3 #define DKIMS_SI_SIGERROR 4 #define DKIMS_SI_DNSSEC 5 #define DKIMS_SI_MAX 5 /* PROTOTYPES */ extern void dkimf_stats_init __P((void)); extern int dkimf_stats_record __P((char *, u_char *, char *, char *, Header, DKIM *, #ifdef _FFR_STATSEXT struct statsext *, #endif /* _FFR_STATSEXT */ int, int, struct sockaddr *)); #endif /* _STATS_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/test.c000066400000000000000000000425161337314105200214160ustar00rootroot00000000000000/* ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. */ /* system includes */ #include #include #include #include #include #include #include #include #include #include /* libopendkim includes */ #include "build-config.h" #include /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* libmilter includes */ #include /* opendkim includes */ #define DKIMF_MILTER_PROTOTYPES #include "test.h" #include "opendkim.h" /* local types and definitions*/ #define CRLF "\r\n" struct test_context { void * tc_priv; /* private data pointer */ }; char *milter_status[] = { "SMFIS_CONTINUE", "SMFIS_REJECT", "SMFIS_DISCARD", "SMFIS_ACCEPT", "SMFIS_TEMPFAIL" }; char *envfrom[] = { "", NULL }; char *envrcpt[] = { "", NULL }; #define FCLOSE(x) if ((x) != stdin) \ fclose((x)); #define MLFI_OUTPUT(x,y) ((y) > 1 || ((y) == 1 && (x) != SMFIS_CONTINUE)) #define STRORNULL(x) ((x) == NULL ? "(null)" : (x)) /* globals */ static int tverbose = 0; /* ** DKIMF_TEST_SETPRIV -- store private pointer ** ** Parameters: ** ctx -- context pointer ** ptr -- pointer to store ** ** Return value: ** MI_SUCCESS */ int dkimf_test_setpriv(void *ctx, void *ptr) { struct test_context *tc; assert(ctx != NULL); tc = ctx; tc->tc_priv = ptr; return MI_SUCCESS; } /* ** DKIMF_TEST_GETPRIV -- retrieve private pointer ** ** Parameters: ** ctx -- context pointer ** ** Return value: ** The private pointer. */ void * dkimf_test_getpriv(void *ctx) { struct test_context *tc; assert(ctx != NULL); tc = ctx; return tc->tc_priv; } /* ** DKIMF_TEST_PROGRESS -- send progress message ** ** Parameters: ** ctx -- context pointer ** ** Return value: ** MI_SUCCESS */ int dkimf_test_progress(void *ctx) { assert(ctx != NULL); if (tverbose > 1) fprintf(stdout, "### PROGRESS\n"); return MI_SUCCESS; } /* ** DKIMF_TEST_SETREPLY -- set reply to use ** ** Parameters: ** ctx -- context pointer ** rcode -- SMTP reply code ** xcode -- SMTP enhanced reply code ** replytxt -- SMTP reply text ** ** Return value: ** MI_SUCCESS */ int dkimf_test_setreply(void *ctx, char *rcode, char *xcode, char *replytxt) { assert(ctx != NULL); if (tverbose > 1) { fprintf(stdout, "### SETREPLY: rcode='%s' xcode='%s' replytxt='%s'\n", STRORNULL(rcode), STRORNULL(xcode), STRORNULL(replytxt)); } return MI_SUCCESS; } /* ** DKIMF_TEST_INSHEADER -- insert a header ** ** Parameters: ** ctx -- context pointer ** idx -- insertion index ** hname -- header name ** hvalue -- header value ** ** Return value: ** MI_SUCCESS */ int dkimf_test_insheader(void *ctx, int idx, char *hname, char *hvalue) { assert(ctx != NULL); if (tverbose > 1) { fprintf(stdout, "### INSHEADER: idx=%d hname='%s' hvalue='%s'\n", idx, STRORNULL(hname), STRORNULL(hvalue)); } return MI_SUCCESS; } /* ** DKIMF_TEST_CHGHEADER -- change a header ** ** Parameters: ** ctx -- context pointer ** hname -- header name ** idx -- header index ** hvalue -- header value ** ** Return value: ** MI_SUCCESS */ int dkimf_test_chgheader(void *ctx, char *hname, int idx, char *hvalue) { assert(ctx != NULL); if (tverbose > 1) { fprintf(stdout, "### CHGHEADER: hname='%s' idx=%d hvalue='%s'\n", STRORNULL(hname), idx, STRORNULL(hvalue)); } return MI_SUCCESS; } /* ** DKIMF_TEST_QUARANTINE -- request message quarantine ** ** Parameters: ** ctx -- context pointer ** reason -- reason string ** ** Return value: ** MI_SUCCESS */ int dkimf_test_quarantine(void *ctx, char *reason) { assert(ctx != NULL); if (tverbose > 1) { fprintf(stdout, "### QUARANTINE: reason='%s'\n", STRORNULL(reason)); } return MI_SUCCESS; } /* ** DKIMF_TEST_ADDHEADER -- append a header ** ** Parameters: ** ctx -- context pointer ** hname -- header name ** hvalue -- header value ** ** Return value: ** MI_SUCCESS */ int dkimf_test_addheader(void *ctx, char *hname, char *hvalue) { assert(ctx != NULL); if (tverbose > 1) { fprintf(stdout, "### ADDHEADER: hname='%s' hvalue='%s'\n", STRORNULL(hname), STRORNULL(hvalue)); } return MI_SUCCESS; } /* ** DKIMF_TEST_DELRCPT -- request recipient delete ** ** Parameters: ** ctx -- context pointer ** addr -- address ** ** Return value: ** MI_SUCCESS */ int dkimf_test_delrcpt(void *ctx, char *addr) { assert(ctx != NULL); assert(addr != NULL); if (tverbose > 1) fprintf(stdout, "### DELRCPT: '%s'\n", addr); return MI_SUCCESS; } /* ** DKIMF_TEST_ADDRCPT -- request recipient add ** ** Parameters: ** ctx -- context pointer ** addr -- address ** ** Return value: ** MI_SUCCESS */ int dkimf_test_addrcpt(void *ctx, char *addr) { assert(ctx != NULL); assert(addr != NULL); if (tverbose > 1) fprintf(stdout, "### ADDRCPT: '%s'\n", addr); return MI_SUCCESS; } /* ** DKIMF_TEST_GETSYMVAL -- retrieve a symbol value ** ** Parameters: ** ctx -- context pointer ** sym -- symbol name ** ** Return value: ** Pointer to (static) string name. ** ** Note: ** This isn't thread-safe, but test mode is single-threaded anyway. ** This is also a memory leak, but it's a short-lived test program ** anyway. */ char * dkimf_test_getsymval(void *ctx, char *sym) { static char symout[MAXBUFRSZ]; assert(ctx != NULL); assert(sym != NULL); snprintf(symout, sizeof symout, "DEBUG-%s", sym); return strdup(symout); } /* ** DKIMF_TESTFILE -- read a message and test it ** ** Parameters: ** libopendkim -- DKIM_LIB handle ** file -- input file path ** fixedtime -- time to use on signatures (or -1) ** strict -- strict CRLF mode? ** verbose -- verbose level ** ** Return value: ** An EX_* constant (see sysexits.h) */ static int dkimf_testfile(DKIM_LIB *libopendkim, struct test_context *tctx, FILE *f, char *file, _Bool strict, int tverbose) { bool inheaders = TRUE; bool newline = FALSE; int len = 0; int buflen = 0; int lineno = 0; int hslineno = 0; int c; DKIM_SIGINFO *sig; struct signreq *srlist = NULL; DKIM *dkim; char *p; sfsistat ms; char buf[MAXBUFRSZ]; char line[MAXBUFRSZ]; assert(libopendkim != NULL); assert(tctx != NULL); assert(f != NULL); memset(buf, '\0', sizeof buf); memset(line, '\0', sizeof buf); ms = mlfi_envfrom((SMFICTX *) tctx, envfrom); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_envfrom() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; ms = mlfi_envrcpt((SMFICTX *) tctx, envrcpt); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_envrcpt() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; while (!feof(f)) { if (fgets(line, sizeof line, f) == NULL) break; lineno++; c = '\0'; newline = FALSE; for (p = line; *p != '\0'; p++) { if (*p == '\n') { newline = TRUE; *p = '\0'; break; } c = *p; } if (c != '\r') { if (strict) /* error */ { fprintf(stderr, "%s: %s: line %d: not CRLF-terminated\n", progname, file, lineno); return EX_DATAERR; } } else if (p != line) /* eat the CR */ { *(p - 1) = '\0'; } if (inheaders) { if (line[0] == '\0') { if (buf[0] != '\0') { char *colon; colon = strchr(buf, ':'); if (colon == NULL) { fprintf(stderr, "%s: %s: line %d: header malformed\n", progname, file, lineno); return EX_DATAERR; } *colon = '\0'; if (*(colon + 1) == ' ') colon++; ms = mlfi_header((SMFICTX *) tctx, buf, colon + 1); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: line %d: mlfi_header() returned %s\n", progname, file, hslineno, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; } inheaders = FALSE; memset(buf, '\0', sizeof buf); memset(line, '\0', sizeof buf); ms = mlfi_eoh((SMFICTX *) tctx); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_eoh() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; continue; } if (line[0] == ' ' || line[0] == '\t') { (void) strlcat(buf, CRLF, sizeof buf); if (strlcat(buf, line, sizeof buf) >= sizeof buf) { fprintf(stderr, "%s: %s: line %d: header '%*s...' too large\n", progname, file, lineno, 20, buf); return EX_DATAERR; } } else { if (buf[0] != '\0') { char *colon; colon = strchr(buf, ':'); if (colon == NULL) { fprintf(stderr, "%s: %s: line %d: header malformed\n", progname, file, lineno); return EX_DATAERR; } *colon = '\0'; if (*(colon + 1) == ' ') colon++; ms = mlfi_header((SMFICTX *) tctx, buf, colon + 1); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: line %d: mlfi_header() returned %s\n", progname, file, hslineno, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; hslineno = 0; } if (hslineno == 0) hslineno = lineno; strlcpy(buf, line, sizeof buf); } } else { len = strlen(line); if (len + buflen >= (int) sizeof buf - 3) { ms = mlfi_body((SMFICTX *) tctx, (u_char *) buf, strlen(buf)); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_body() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; memset(buf, '\0', sizeof buf); buflen = 0; } memcpy(&buf[buflen], line, len); buflen += len; if (newline) { memcpy(&buf[buflen], CRLF, 2); buflen += 2; } } } /* unprocessed partial header? */ if (inheaders && buf[0] != '\0') { char *colon; colon = strchr(buf, ':'); if (colon == NULL) { fprintf(stderr, "%s: %s: line %d: header malformed\n", progname, file, lineno); return EX_DATAERR; } *colon = '\0'; if (*(colon + 1) == ' ') colon++; ms = mlfi_header((SMFICTX *) tctx, buf, colon + 1); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: line %d: mlfi_header() returned %s\n", progname, file, lineno, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; ms = mlfi_eoh((SMFICTX *) tctx); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_eoh() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; inheaders = FALSE; memset(buf, '\0', sizeof buf); } /* no headers found */ if (inheaders) { fprintf(stderr, "%s: %s: warning: no headers on input\n", progname, file); ms = mlfi_eoh((SMFICTX *) tctx); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_eoh() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; } /* some body left */ if (!inheaders && buf[0] != '\0') { ms = mlfi_body((SMFICTX *) tctx, (u_char *) buf, strlen(buf)); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_body() returned %s\n", progname, file, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; } ms = mlfi_eom((SMFICTX *) tctx); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: %s: mlfi_eom() returned %s\n", progname, file, milter_status[ms]); } dkim = dkimf_getdkim(tctx->tc_priv); if (dkim != NULL) { int mode; mode = dkim_getmode(dkim); sig = dkim_getsignature(dkim); if (sig != NULL) { const u_char *domain; const u_char *selector; u_int flags; u_int bh; u_int keysize; domain = dkim_sig_getdomain(sig); selector = dkim_sig_getselector(sig); flags = dkim_sig_getflags(sig); bh = dkim_sig_getbh(sig); dkim_sig_getkeysize(sig, &keysize); if ((flags & DKIM_SIGFLAG_PASSED) != 0 && bh == DKIM_SIGBH_MATCH) { fprintf(stdout, "%s: %s: verification (s=%s, d=%s, %d-bit key) succeeded\n", progname, file, selector, domain, keysize); } else { const char *err; int errcode; errcode = dkim_sig_geterror(sig); if (errcode == DKIM_SIGERROR_OK && bh == DKIM_SIGBH_MISMATCH) err = "body hash mismatch"; else err = dkim_sig_geterrorstr(errcode); if (selector != NULL || domain != NULL) { char *dnssec; int dnsseccode = DKIM_DNSSEC_UNKNOWN; dnsseccode = dkim_sig_getdnssec(sig); switch (dnsseccode) { case DKIM_DNSSEC_BOGUS: dnssec = "bogus"; break; case DKIM_DNSSEC_INSECURE: dnssec = "insecure"; break; case DKIM_DNSSEC_SECURE: dnssec = "secure"; break; case DKIM_DNSSEC_UNKNOWN: default: dnssec = "unknown"; break; } fprintf(stdout, "%s: %s: verification (s=%s d=%s, %d-bit key, %s) failed: %s\n", progname, file, selector, domain, keysize, dnssec, err); } else { fprintf(stdout, "%s: %s: verification failed: %s\n", progname, file, err); } } } else if (sig == NULL && mode == DKIM_MODE_VERIFY) { fprintf(stdout, "%s: %s: message not signed\n", progname, file); } } for (srlist = dkimf_getsrlist(tctx->tc_priv); srlist != NULL; srlist = srlist->srq_next) { dkim = srlist->srq_dkim; sig = dkim_getsignature(dkim); if (sig == NULL) { const char *err; err = dkim_geterror(dkim); if (err == NULL) err = "unknown error"; fprintf(stdout, "%s: %s: no signature added: %s\n", progname, file, err); } else { if (tverbose < 2) { DKIM_STAT status; size_t hlen; size_t rem; unsigned char hdr[DKIM_MAXHEADER + 1]; hlen = strlen(DKIM_SIGNHEADER); rem = sizeof hdr - hlen - 2; memset(hdr, '\0', sizeof hdr); strlcpy((char *) hdr, DKIM_SIGNHEADER ": ", sizeof hdr); status = dkim_getsighdr(dkim, hdr + hlen + 2, rem, hlen + 2); if (status != DKIM_STAT_OK) { fprintf(stderr, "%s: %s: dkim_getsighdr(): %s\n", progname, file, dkim_getresultstr(status)); } else { fprintf(stdout, "%s: %s:\n%s\n", progname, file, hdr); } } } } return EX_OK; } /* ** DKIMF_TESTFILES -- test one or more input messages ** ** Parameters: ** libopendkim -- DKIM_LIB handle ** flist -- input file list ** fixedtime -- time to use on signatures (or -1) ** strict -- strict CRLF mode? ** verbose -- verbose level ** ** Return value: ** An EX_* constant (see sysexits.h) */ int dkimf_testfiles(DKIM_LIB *libopendkim, char *flist, uint64_t fixedtime, bool strict, int verbose) { char *file; char *ctx; FILE *f; int status; sfsistat ms; struct test_context *tctx; struct sockaddr_in sin; assert(libopendkim != NULL); assert(flist != NULL); tverbose = verbose; /* pass fixed signing time to the library */ if (fixedtime != (uint64_t) -1) { (void) dkim_options(libopendkim, DKIM_OP_SETOPT, DKIM_OPTS_FIXEDTIME, &fixedtime, sizeof fixedtime); } /* set up a fake SMFICTX */ tctx = (struct test_context *) malloc(sizeof(struct test_context)); if (tctx == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return EX_OSERR; } tctx->tc_priv = NULL; (void) memset(&sin, '\0', sizeof sin); sin.sin_family = AF_INET; sin.sin_port = htons(time(NULL) % 65536); sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); ms = mlfi_connect((SMFICTX *) tctx, "localhost", (_SOCK_ADDR *) &sin); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: mlfi_connect() returned %s\n", progname, milter_status[ms]); } if (ms != SMFIS_CONTINUE) return EX_SOFTWARE; /* loop through inputs */ for (file = strtok_r(flist, ",", &ctx); file != NULL; file = strtok_r(NULL, ",", &ctx)) { /* open the input */ if (strcmp(file, "-") == 0) { f = stdin; file = "(stdin)"; } else { f = fopen(file, "r"); if (f == NULL) { fprintf(stderr, "%s: %s: fopen(): %s\n", progname, file, strerror(errno)); return EX_UNAVAILABLE; } } status = dkimf_testfile(libopendkim, tctx, f, file, strict, tverbose); FCLOSE(f); if (status != EX_OK) return status; } ms = mlfi_close((SMFICTX *) tctx); if (MLFI_OUTPUT(ms, tverbose)) { fprintf(stderr, "%s: mlfi_close() returned %s\n", progname, milter_status[ms]); } return EX_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/test.h000066400000000000000000000021501337314105200214110ustar00rootroot00000000000000/* ** Copyright (c) 2007 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. ** */ #ifndef _TEST_H_ #define _TEST_H_ /* system includes */ #include #include /* libmilter includes */ #include /* libopendkim includes */ #include "dkim.h" /* PROTOTYPES */ extern int dkimf_testfiles __P((DKIM_LIB *, char *, uint64_t, bool, int)); extern int dkimf_test_addheader __P((void *, char *, char *)); extern int dkimf_test_addrcpt __P((void *, char *)); extern int dkimf_test_chgheader __P((void *, char *, int, char *)); extern int dkimf_test_delrcpt __P((void *, char *)); extern void *dkimf_test_getpriv __P((void *)); extern char *dkimf_test_getsymval __P((void *, char *)); extern int dkimf_test_insheader __P((void *, int, char *, char *)); extern int dkimf_test_progress __P((void *)); extern int dkimf_test_quarantine __P((void *, char *)); extern int dkimf_test_setpriv __P((void *, void *)); extern int dkimf_test_setreply __P((void *, char *, char *, char *)); #endif /* _TEST_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/000077500000000000000000000000001337314105200214255ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/.gitignore000066400000000000000000000010521337314105200234130ustar00rootroot00000000000000*.o *.lo *.la *.a *~ *.pc *.gcda *.gcno *.gmon *.prof *.info *.gcov *.trs *.log t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ .info-files autom4te.cache/ autoscan-*.log build-config.h.in compile config.guess config.sub configure configure.scan aclocal.m4 description.html description.txt depcomp install-sh missing stamp-h* build-config.h config.log config.status ltmain.sh libtool Makefile.in Makefile symbols.map .libs .deps core *.core opendkim-testadsp opendkim opendkim-stats opendkim-testkey opendkim*.[58] test.sock gmon.out OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/Makefile.am000066400000000000000000000136671337314105200234760ustar00rootroot00000000000000check_SCRIPTS = t-sign-ss t-sign-rs t-sign-rs-tables t-sign-rs-tables-bad \ t-sign-rs-tables-token t-sign-rs-multiple t-sign-rs-mixconf \ t-sign-rs-lua t-sign-ss-all t-sign-ss-ltag t-sign-ss-x \ t-verify-revoked t-verify-unspec t-verify-malformed \ t-verify-unsigned t-verify-unsigned-silent \ t-verify-syntax t-verify-ss t-verify-ss-header-fields t-verify-ss-bad \ t-verify-ss-ar-bad \ t-dontsign t-peer \ t-lua-verify-tests t-sign-ss-macro t-sign-ss-macro-value \ t-sign-ss-macro-value-file t-verify-report \ t-sign-report t-conf-check t-verify-double-from if LIVE_TESTS if RBL check_SCRIPTS += t-lua-rbl endif endif if REPUTE check_SCRIPTS += t-verify-ss-rep endif if REPLACE_RULES check_SCRIPTS += t-sign-ss-replace endif if ATPS check_SCRIPTS += t-sign-atps t-verify-ss-atps endif if CONDITIONAL check_SCRIPTS += t-sign-ss-conditional endif if TEST_SOCKET TESTS_ENVIRONMENT = MILTERTESTFLAGS=-DTESTSOCKET=$(TESTSOCKET); export MILTERTESTFLAGS; endif TESTS = $(check_SCRIPTS) EXTRA_DIST = \ t-sign-rs t-sign-rs.conf t-sign-rs.lua \ t-sign-rs-lua t-sign-rs-lua.conf t-sign-rs-lua.keys \ t-sign-rs-lua.lua t-sign-rs-lua.lua-setup t-sign-rs-lua.sign \ t-sign-rs-mixconf t-sign-rs-mixconf.keys t-sign-rs-mixconf.conf \ t-sign-rs-mixconf.lua t-sign-rs-mixconf.lua-setup \ t-sign-rs-multiple t-sign-rs-multiple.conf t-sign-rs-multiple.keys \ t-sign-rs-multiple.lua t-sign-rs-multiple.sign \ t-sign-rs-tables t-sign-rs-tables.conf t-sign-rs-tables.keys \ t-sign-rs-tables.lua t-sign-rs-tables.sign \ t-sign-rs-tables-bad t-sign-rs-tables-bad.conf \ t-sign-rs-tables-bad.keys t-sign-rs-tables-bad.lua \ t-sign-rs-tables-token t-sign-rs-tables-token.conf \ t-sign-rs-tables-token.keys t-sign-rs-tables-token.lua \ t-sign-ss t-sign-ss.conf t-sign-ss.lua \ t-sign-ss-x t-sign-ss-x.conf t-sign-ss-x.lua \ t-sign-ss-all t-sign-ss-all.conf t-sign-ss-all.lua \ t-sign-ss-ltag t-sign-ss-ltag.conf t-sign-ss-ltag.lua \ t-sign-ss-macro t-sign-ss-macro.conf t-sign-ss-macro.lua \ t-sign-ss-macro-value t-sign-ss-macro-value.conf \ t-sign-ss-macro-value.lua \ t-sign-ss-macro-value-file t-sign-ss-macro-value-file.conf \ t-sign-ss-macro-value-file.lua \ t-sign-ss-macro-value-file.list \ t-sign-ss-replace t-sign-ss-replace.conf t-sign-ss-replace.lua \ t-sign-ss-replace.txt \ t-sign-report t-sign-report.conf t-sign-report.lua \ t-sign-ss-conditional t-sign-ss-conditional.conf \ t-sign-ss-conditional.lua \ t-verify-revoked t-verify-revoked.conf t-verify-revoked.lua \ t-verify-unsigned t-verify-unsigned.conf t-verify-unsigned.lua \ t-verify-malformed t-verify-malformed.conf t-verify-malformed.lua \ t-verify-unsigned-silent t-verify-unsigned-silent.conf \ t-verify-unsigned-silent.lua \ t-verify-unspec t-verify-unspec.conf t-verify-unspec.lua \ t-verify-ss t-verify-ss.conf t-verify-ss.lua \ t-verify-ss-header-fields t-verify-ss-header-fields.conf t-verify-ss-header-fields.lua \ t-verify-ss-bad t-verify-ss-bad.conf t-verify-ss-bad.lua \ t-verify-ss-ar-bad t-verify-ss-ar-bad.conf t-verify-ss-ar-bad.lua \ t-verify-ss-rep t-verify-ss-rep.conf t-verify-ss-rep.lua \ t-verify-syntax t-verify-syntax.conf t-verify-syntax.lua \ t-verify-double-from t-verify-double-from.conf \ t-verify-double-from.lua \ t-dontsign t-dontsign.conf t-dontsign.lua \ t-lua-rbl t-lua-rbl.conf t-lua-rbl.lua t-lua-rbl.lua-final \ t-lua-verify-tests t-lua-verify-tests.lua t-lua-verify-tests.conf \ t-lua-verify-tests.lua-setup \ t-peer t-peer.conf t-peer.list t-peer.lua \ t-verify-report t-verify-report.conf t-verify-report.txt \ t-verify-report.lua \ t-sign-atps t-sign-atps.conf t-sign-atps.lua \ t-verify-ss-atps t-verify-ss-atps.conf t-verify-ss-atps.lua \ t-conf-check t-conf-check.conf t-conf-check.keytable t-conf-check.lua \ t-conf-check.signtable t-conf-check2.conf \ t-conf-check2.keytable t-conf-check2.lua \ t-conf-check2.signtable t-largecomment.conf \ testkey.private pubkeys cp-test testmta MOSTLYCLEANFILES= if GCOV_ONLY MOSTLYCLEANFILES+=*.gcov *.gcno *.gcda *.bb *.bbg *.da .gcov-files #PROF_SRCS= opendkim.c opendkim.h opendkim-ar.c opendkim-ar.h opendkim-arf.c opendkim-arf.h opendkim-config.h opendkim-crypto.c opendkim-crypto.h opendkim-db.c opendkim-db.h opendkim-lua.c opendkim-lua.h config.c #TESTS_ENVIRONMENT=./gcov-helper.sh #.gcov-files: check-TESTS # for i in $(PROF_SRCS); do \ # x=`echo $$i | sed 's/\..*//g'`; \ # if test -f ../libopendkim_la-$$x.gcno -a \ # -f ../libopendkim_la-$$x.gcda; then \ # mv ../libopendkim_la-$$x.gcno ../$$x.gcno; \ # mv ../libopendkim_la-$$x.gcda ../$$x.gcda; \ # gcov -o .. $$i; \ # fi; \ # if test -f ../libopendkim_la-$$x.bb -a \ # -f ../libopendkim_la-$$x.bbg -a \ # -f ../libopendkim_la-$$x.da; then \ # mv ../libopendkim_la-$$x.bb ../$$x.bb; \ # mv ../libopendkim_la-$$x.bbg ../$$x.bbg; \ # mv ../libopendkim_la-$$x.da ../$$x.da; \ # gcov -o .. $$i; \ # fi; \ # done # touch $@ # #check-local: .gcov-files endif if LCOV dist_doc_DATA=lcov MAINTAINERCLEANFILES=description.txt description.html MOSTLYCLEANFILES+=*.info .prepare-lcov .info-files *.gcno *.gcda TESTS_ENVIRONMENT=./lcov-helper.sh #.info-files: check-TESTS # for i in $(TESTS); do \ # lcov --capture --directory $(top_builddir) --output-file $$i.info \ # --test-name $$i -q; \ # done # touch .info-files check-local: check-TESTS description.html genhtml --output-directory lcov *.info --show-details --highlight \ --frames --legend --title @PACKAGE@ \ --description-file description.html description.txt: $(check_SCRIPTS) rm -f $@ for test in $? ; do \ testname=$${test/t-}; \ testname=$${testname//-/_}; \ grep ^# $$test | tail -n 1 | \ sed -e "s/^#\(.*\)/$${testname}\n\t\1\n/g" >> $@; \ done description.html: description.txt gendesc --output $@ $< maintainer-clean-local: -rm -rf lcov/[^C]* .PHONY: maintainer-clean-local check-local endif if GPROF MOSTLYCLEANFILES+=*.prof gmon.out *.gmon check-local: check-TESTS for i in $(check_PROGRAMS); do \ ./$$i; \ gprof $$i > $$i.prof; \ done endif OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/README000066400000000000000000000002511337314105200223030ustar00rootroot00000000000000 This directory contains unit tests run against the filter, written using the Lua language and executed via the "miltertest" tool found below the main source directory. OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/cp-test000077500000000000000000000005321337314105200227320ustar00rootroot00000000000000#!/bin/sh # small tool to copy a test case # XXX TODO arg 3 should be a description approprately inserted to the files if [ $# -lt 2 ] then echo requires more parameters echo usage: $0 fromtestcasename totestcasename exit 1 fi for a in $1 $1.*; do dest=${a/$1/$2} echo copying $a to $dest sed -e s/$1/$2/g $a > $dest done chmod a+x $2 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/gcov-helper.sh000077500000000000000000000003551337314105200242020ustar00rootroot00000000000000#!/bin/sh $1 x=$? myname=`basename $1` if test x"$OSTYPE" = x"OpenBSD" then mv *$myname.bb $myname.bb mv *$myname.bbg $myname.bbg mv *$myname.da $myname.da else mv *$myname.gcda $myname.gcda mv *$myname.gcno $myname.gcno fi exit $x OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/lcov-helper.sh000077500000000000000000000004111337314105200242000ustar00rootroot00000000000000#!/bin/sh $1 x=$? # keep consistant with Makefile.am testname=${1/.\/t-} testname=${testname//-/_} lcov --capture --directory ../.. --output-file $1.info --test-name ${testname} --quiet lcov --remove $1.info '/usr/include/*' --output-file $1.info --quiet & exit $x OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/lcov/000077500000000000000000000000001337314105200223705ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/lcov/.gitignore000066400000000000000000000000071337314105200243550ustar00rootroot00000000000000[a-z]* OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/lcov/README000066400000000000000000000002771337314105200232560ustar00rootroot00000000000000This directory will contain the output of an "lcov" (code coverage) report run during packaging of this release. To read it, point your favourite browser at "index.html" in this directory. OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/pubkeys000066400000000000000000000014401337314105200230310ustar00rootroot00000000000000example2.com foo _adsp._domainkey.example2.com dkim=all; ra=adsp-feedback revoked._domainkey.example.com k=rsa; t=y; p= _report._domainkey.example.com ra=dkim-feedbacks UN42N5XOV642KXRXRQIYANHCOUPGQL5LT4WTBKYT2IJFLBWODFDQ====._atps.example.net v=ATPS1 report._domainkey.example.com v=DKIM1; k=rsa; r=dkim-feedbacks; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9p5rp5EjC8cZbnlUpasA5HoUYwSA+HEBsBZnxppmehsiCLY/rSGDxmYaOL2LhGJur4UnXzTRpB/VgPTNOn3bkudEARqu0H2W6afEcI46igMs8fuZlyIi+UMGdUbn5tgbTRS7g6r9bxOcxwTtZcKAhvCWfDiTc2QeEzzxxyL4jewIDAQAB test._domainkey.example.com v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9p5rp5EjC8cZbnlUpasA5HoUYwSA+HEBsBZnxppmehsiCLY/rSGDxmYaOL2LhGJur4UnXzTRpB/VgPTNOn3bkudEARqu0H2W6afEcI46igMs8fuZlyIi+UMGdUbn5tgbTRS7g6r9bxOcxwTtZcKAhvCWfDiTc2QeEzzxxyL4jewIDAQAB OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check000077500000000000000000000012601337314105200236130ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2012, 2013, The Trusted Domain Project. All rights reserved. # # Configuration validity check echo "*** configuration validity checks" if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi if ../../miltertest/miltertest -s $srcdir/t-conf-check.lua > /dev/null 2>&1 then echo ERROR: opendkim started with a faulty configuration exit 1 fi if ../../miltertest/miltertest -s $srcdir/t-conf-check2.lua > /dev/null 2>&1 then echo ERROR: opendkim started with a faulty configuration exit 1 fi if ! ../opendkim -n -x $srcdir/t-largecomment.conf > /dev/null 2>&1 then echo ERROR: opendkim failed using a configuration file with a large comment exit 1 fi exit 0 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check.conf000066400000000000000000000003211337314105200245310ustar00rootroot00000000000000# Copyright (c) 2012, The Trusted Domain Project. All rights reserved. # # Configuration validity check Background No Mode s SigningTable file:t-conf-check.signtable KeyTable file:t-conf-check.keytable OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check.keytable000066400000000000000000000000441337314105200254060ustar00rootroot00000000000000key1 example.com:ts:testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check.lua000066400000000000000000000013041337314105200243670ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- Configuration validity check -- -- Confirms that the configuration file is acceptable (fail test) mt.echo("*** invalid signing configuration test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-conf-check.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-conf-check.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn ~= nil then error("mt.connect() succeeded (shouldn't have)") end OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check.signtable000066400000000000000000000000421337314105200255540ustar00rootroot00000000000000example.com key1 example.net key2 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check2.conf000066400000000000000000000003261337314105200246200ustar00rootroot00000000000000# Copyright (c) 2012, The Trusted Domain Project. All rights reserved. # # Configuration validity check #2 Background No Mode s SigningTable file:t-conf-check2.signtable KeyTable file:t-conf-check2.keytable OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check2.keytable000066400000000000000000000000701337314105200254670ustar00rootroot00000000000000key1 example.com:ts:testkey.private key2 example.net:ts OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check2.lua000066400000000000000000000013071337314105200244540ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- Configuration validity check2 -- -- Confirms that the configuration file is acceptable (fail test) mt.echo("*** invalid signing configuration test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-conf-check2.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-conf-check2.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn ~= nil then error("mt.connect() succeeded (shouldn't have)") end OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-conf-check2.signtable000066400000000000000000000000421337314105200256360ustar00rootroot00000000000000example.com key1 example.net key2 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-dontsign000077500000000000000000000002361337314105200234420ustar00rootroot00000000000000#!/bin/sh # # # "DontSignMailTo" test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-dontsign.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-dontsign.conf000066400000000000000000000002421337314105200243600ustar00rootroot00000000000000# # "DontSignMailTo" test Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test DontSignMailTo recipient@example.org OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-dontsign.lua000066400000000000000000000042401337314105200242160ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- "DontSignMailTo" test -- -- Confirms that a signature is not added for a specific recipient. mt.echo("*** DontSignMailTo test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-dontsign.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-dontsign.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-dontsign") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send envelope macros and recipient data if mt.rcptto(conn, "recipient@example.org") ~= nil then error("mt.rcptto() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.rcptto() unexpected reply") end -- send headers if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eoh() unexpected reply") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-largecomment.conf000066400000000000000000000612421337314105200252170ustar00rootroot00000000000000#This big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big big line should be ignored by the parser Mode v OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-rbl000077500000000000000000000002751337314105200231560ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple verifying test using Lua's RBL feature if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-lua-rbl.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-rbl.conf000066400000000000000000000002511337314105200240710ustar00rootroot00000000000000# # Lua RBL test configuration Background No Canonicalization relaxed/simple RequireSafeKeys No FinalPolicyScript t-lua-rbl.lua-final TestPublicKeys pubkeys OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-rbl.lua000066400000000000000000000074541337314105200237410ustar00rootroot00000000000000-- Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. -- Lua RBL hook test mt.echo("*** Lua RBL hook test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-lua-rbl.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-lua-rbl.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-lua-rbl") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end c = 0 found = false foundpass = false while found == false do ar = mt.getheader(conn, "Authentication-Results", c) if ar == nil then break end if string.find(ar, "dkim=", 1, true) ~= nil then found = true if string.find(ar, "dkim=pass", 1, true) ~= nil then foundpass = true break end end c = c + 1 end if not found then error("DKIM result not found") elseif found and not foundpass then error("incorrect DKIM result") end -- verify that an X-Lua-RBL header field got added with the right value if not mt.eom_check(conn, MT_HDRINSERT, "X-Lua-RBL") and not mt.eom_check(conn, MT_HDRADD, "X-Lua-RBL") then error("no X-Lua-RBL header field added") end ar = mt.getheader(conn, "X-Lua-RBL", 0) if ar ~= "127.0.0.2" then error("incorrect RBL result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-rbl.lua-final000066400000000000000000000005661337314105200250250ustar00rootroot00000000000000 -- Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. -- sample "final" hook script that issues an RBL query -- make the RBL request a,b,c,d = odkim.rbl_check(ctx, "2.0.0.127", "sbl.spamhaus.org") odkim.add_header(ctx, "X-Lua-RBL", tostring(a) .. "." .. tostring(b) .. "." .. tostring(c) .. "." .. tostring(d)) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-speed000077500000000000000000000005221337314105200234720ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing speed test with and without Lua if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi echo ===== signing without Lua ../../miltertest/miltertest $MILTERTESTFLAGS -u -s $srcdir/t-lua-speed-nolua.lua echo ===== signing with Lua ../../miltertest/miltertest $MILTERTESTFLAGS -u -s $srcdir/t-lua-speed-lua.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-speed-lua.conf000066400000000000000000000002411337314105200251700ustar00rootroot00000000000000# # simple/simple signing test with Lua Background No RequireSafeKeys No KeyFile testkey.private Selector test SetupPolicyScript t-lua-speed-lua.lua-setup OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-speed-lua.lua000066400000000000000000000053221337314105200250310ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test with Lua -- -- For comparing performance with and without Lua mt.echo("*** simple/simple signing test with Lua, 1000 messages") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-lua-speed-lua.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-lua-speed-lua.conf", "-p", sock) for x = 1, 1000 do -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed", conn)) end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-lua-speed-lua") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- disconnect mt.disconnect(conn) end OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-speed-lua.lua-setup000066400000000000000000000003131337314105200261620ustar00rootroot00000000000000 -- Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. -- All rights reserved. -- sample "setup" hook script that issues a single signing request -- make the signing request odkim.sign(ctx) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-speed-nolua.conf000066400000000000000000000002151337314105200255260ustar00rootroot00000000000000# # simple/simple signing test without Lua Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-speed-nolua.lua000066400000000000000000000053401337314105200253660ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test without Lua -- -- For comparing performance with and without Lua mt.echo("*** simple/simple signing test without Lua, 1000 messages") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-lua-speed-nolua.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-lua-speed-nolua.conf", "-p", sock) for x = 1, 1000 do -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error( "mt.connect() failed " , conn) end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-lua-speed-nolua") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- disconnect mt.disconnect(conn) end OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-verify-tests000077500000000000000000000002321337314105200250340ustar00rootroot00000000000000#!/bin/sh # # # Lua tests if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-lua-verify-tests.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-verify-tests.conf000066400000000000000000000002531337314105200257600ustar00rootroot00000000000000# # simple/simple verifying test with Lua features TestPublicKeys pubkeys Mode v On-BadSignature reject Background No SetupPolicyScript t-lua-verify-tests.lua-setup OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-verify-tests.lua000066400000000000000000000072141337314105200256200ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple verify test using Lua features mt.echo("*** simple/simple verifying test using Lua features") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-lua-verify-tests.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-lua-verify-tests.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-lua-verify-tests") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@host.example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end if mt.header(conn, "X-Test-Header", "oldvalue") ~= nil then error("mt.header(X-Test-Header) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(X-Test-Header) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end -- verify that a DKIM pass result was added n = 0 found = 0 while true do ar = mt.getheader(conn, "Authentication-Results", n) if ar == nil then break end if string.find(ar, "dkim=pass", 1, true) ~= nil then found = 1 break end n = n + 1 end if found == 0 then error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-lua-verify-tests.lua-setup000066400000000000000000000003651337314105200267560ustar00rootroot00000000000000 -- Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. -- sample "setup" hook script that does various Lua things -- change the From: header field before signing odkim.replace_header(ctx, "From", 0, "user@example.com") OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-peer000077500000000000000000000002411337314105200225440ustar00rootroot00000000000000#!/bin/sh # # # Test of peer IP calculations if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-peer.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-peer.conf000066400000000000000000000002331337314105200234660ustar00rootroot00000000000000# # Test of peer calculations Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test PeerList file:t-peer.list OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-peer.list000066400000000000000000000003041337314105200235130ustar00rootroot00000000000000.example.com !nonpeer.example.com !.nonpeer.example.com allowed.nonpeer.example.com smtp.example.net 192.168.1.0/24 !192.168.1.64 !192.168.1.128/30 2001:db8::/64 !2001:db8::99 !2001:db8::fff0/126 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-peer.lua000066400000000000000000000046411337314105200233310ustar00rootroot00000000000000-- Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. -- PeerList calculation test mt.echo("*** PeerList calculation test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-peer.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-peer.conf", "-p", sock) -- Those in the peer list should have SMFIR_ACCEPT as the result -- to prevent any verification or signing practices test = { -- hostname test { "peer.example.com", "127.0.0.1", SMFIR_ACCEPT }, { "bob.example.com", "127.0.0.1", SMFIR_ACCEPT }, { "bob.example.net", "127.0.0.1", SMFIR_CONTINUE }, { "nonpeer.example.com", "127.0.0.1", SMFIR_CONTINUE }, { "xyz.nonpeer.example.com", "127.0.0.1", SMFIR_CONTINUE }, { "allowed.nonpeer.example.com", "127.0.0.1", SMFIR_ACCEPT }, { "smtp.example.net", "127.0.0.1", SMFIR_ACCEPT }, -- ipv4 tests { "localhost", "127.0.0.1", SMFIR_CONTINUE }, { "localhost", "192.168.1.1", SMFIR_ACCEPT }, { "localhost", "192.168.1.64", SMFIR_CONTINUE }, { "localhost", "192.168.1.128", SMFIR_CONTINUE }, { "localhost", "192.168.1.129", SMFIR_CONTINUE }, { "localhost", "192.168.1.130", SMFIR_CONTINUE }, { "localhost", "192.168.1.131", SMFIR_CONTINUE }, { "localhost", "192.168.1.132", SMFIR_ACCEPT }, -- ipv6 tests { "localhost", "9001:db8::8:800:200c:417a", SMFIR_CONTINUE }, { "localhost", "2001:db8::91", SMFIR_ACCEPT }, { "localhost", "2001:db8::fff0", SMFIR_CONTINUE }, { "localhost", "2001:db8::fff1", SMFIR_CONTINUE }, { "localhost", "2001:db8::fff2", SMFIR_CONTINUE }, { "localhost", "2001:db8::fff3", SMFIR_CONTINUE }, { "localhost", "2001:db8::fff4", SMFIR_ACCEPT } } for index = 1, #test do -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end if mt.conninfo(conn, test[index][1], test[index][2]) ~= nil then stre = "mt.conninfo() failed for " .. test[index][1] .. " (" .. test[index][2] .. ")" error(stre) end if mt.getreply(conn) ~= test[index][3] then stre = "mt.conninfo() unexpected reply " .. test[index][1] .. "(" .. test[index][2] .. ") should be " if test[index][3] == SMFIR_CONTINUE then stre = stre .. "SMFIR_CONTINUE" else stre = stre .. "SMFIR_ACCEPT" end error(stre) end -- disconnect mt.disconnect(conn) end OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-atps000077500000000000000000000002571337314105200235250ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test with ATPS if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-atps.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-atps.conf000066400000000000000000000003261337314105200244430ustar00rootroot00000000000000# # relaxed/simple signing test with ATPS Background No KeyTable csl:key1=example.com:test:./testkey.private SigningTable csl:*=key1 ATPSDomains example.net RequireSafeKeys No Canonicalization relaxed/simple OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-atps.lua000066400000000000000000000065551337314105200243110ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- relaxed/simple signing test with ATPS -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test with ATPS") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-atps.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-atps.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-atps") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.net") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end if string.find(sig, "atps=example.net", 1, true) == nil then error("signature has wrong or missing atps= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-report000077500000000000000000000002711337314105200240650ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test requesting reports if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-report.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-report.conf000066400000000000000000000002511337314105200250040ustar00rootroot00000000000000# # simple/simple signing test requesting reports Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test RequestReports true OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-report.lua000066400000000000000000000066031337314105200246470ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test requesting reports -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test requesting reports") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-report.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-report.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-report") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "r=y", 1, true) == nil then error("signature has wrong or missing r= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs000077500000000000000000000002431337314105200231750ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-lua000077500000000000000000000003031337314105200237510ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test using tables and a Lua hook if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs-lua.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-lua.conf000066400000000000000000000003531337314105200246770ustar00rootroot00000000000000# # relaxed/simple signing test using tables and Lua Background No Canonicalization relaxed/simple RequireSafeKeys No KeyTable file:t-sign-rs-lua.keys SigningTable file:t-sign-rs-lua.sign SetupPolicyScript t-sign-rs-lua.lua-setup OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-lua.keys000066400000000000000000000000541337314105200247230ustar00rootroot00000000000000testkey example.com:test:./testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-lua.lua000066400000000000000000000066371337314105200245460ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple signing test using KeyTable/SigningTable and Lua -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test using tables and Lua") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs-lua.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs-lua.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-lua") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end if string.find(sig, "i=signer@example.com", 1, true) == nil then error("signature has wrong i= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-lua.lua-setup000066400000000000000000000003541337314105200256720ustar00rootroot00000000000000 -- Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. -- All rights reserved. -- sample "setup" hook script that issues a single signing request -- make the signing request odkim.sign(ctx, "testkey", "signer@example.com") OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-lua.sign000066400000000000000000000000311337314105200247030ustar00rootroot00000000000000user@example.com testkey OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-mixconf000077500000000000000000000003201337314105200246320ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test using KeyTable and SetupPolicyScript if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs-mixconf.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-mixconf.conf000066400000000000000000000002701337314105200255570ustar00rootroot00000000000000# # relaxed/simple signing test Background No Canonicalization relaxed/simple RequireSafeKeys No KeyTable file:t-sign-rs-mixconf.keys SetupPolicyScript t-sign-rs-mixconf.lua-setup OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-mixconf.keys000066400000000000000000000000541337314105200256050ustar00rootroot00000000000000testkey example.com:test:./testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-mixconf.lua000066400000000000000000000065271337314105200254260ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple signing test using KeyTable/SetupPolicyScript -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test using KeyTable/SetupPolicyScript") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs-mixconf.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs-mixconf.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-mixconf") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-mixconf.lua-setup000066400000000000000000000003261337314105200265530ustar00rootroot00000000000000 -- Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. -- All rights reserved. -- sample "setup" hook script that issues a single signing request -- make the signing request odkim.sign(ctx, "testkey") OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-multiple000077500000000000000000000002651337314105200250320ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple multiple signing test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs-multiple.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-multiple.conf000066400000000000000000000003471337314105200257540ustar00rootroot00000000000000# # relaxed/simple signing test with multiple signatures Background No Canonicalization relaxed/simple RequireSafeKeys No KeyTable file:t-sign-rs-multiple.keys SigningTable file:t-sign-rs-multiple.sign MultipleSignatures True OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-multiple.keys000066400000000000000000000001311337314105200257710ustar00rootroot00000000000000testkey example.com:test:./testkey.private testkey2 example.net:test2:./testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-multiple.lua000066400000000000000000000102351337314105200256050ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple multiple signing test -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple multiple signing test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs-multiple.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs-multiple.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-multiple") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if sig == nil then error("first signature not added") end if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.net", 1, true) == nil then error("signature has wrong d= value (expecting example.net)") end if string.find(sig, "s=test2", 1, true) == nil then error("signature has wrong s= value (expecting test2)") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end sig = mt.getheader(conn, "DKIM-Signature", 1) if sig == nil then error("second signature not added") end if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value (expecting example.com)") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value (expecting test)") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-multiple.sign000066400000000000000000000000571337314105200257650ustar00rootroot00000000000000user@example.com testkey example.com testkey2 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables000077500000000000000000000002671337314105200244530ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test using tables if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs-tables.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-bad000077500000000000000000000003051337314105200251700ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test using invalid KeyTable if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs-tables-bad.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-bad.conf000066400000000000000000000003141337314105200261110ustar00rootroot00000000000000# # relaxed/simple signing test with invalid KeyTable Background No Canonicalization relaxed/simple RequireSafeKeys No KeyTable file:t-sign-rs-tables-bad.keys SigningTable file:t-sign-rs-tables.sign OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-bad.keys000066400000000000000000000000541337314105200261400ustar00rootroot00000000000000testkey example.com test ./testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-bad.lua000066400000000000000000000041251337314105200257510ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple signing test using KeyTable/SigningTable -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test using invalid KeyTable") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs-tables-bad.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs-tables-bad.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-tables-bad") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_TEMPFAIL then error("mt.eoh() unexpected reply") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-token000077500000000000000000000003251337314105200255640ustar00rootroot00000000000000#!/bin/sh # # # relaxed/simple signing test using KeyTable with the domain token if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-rs-tables-token.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-token.conf000066400000000000000000000003311337314105200265020ustar00rootroot00000000000000# # relaxed/simple signing test with KeyTable using domain token Background No Canonicalization relaxed/simple RequireSafeKeys No KeyTable file:t-sign-rs-tables-token.keys SigningTable file:t-sign-rs-tables.sign OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-token.keys000066400000000000000000000000421337314105200265270ustar00rootroot00000000000000testkey %:test:./testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables-token.lua000066400000000000000000000136311337314105200263450ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple signing test using KeyTable/SigningTable with domain token -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test using KeyTable and domain token") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs-tables-token.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs-tables-token.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-tables-token") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user2@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end if string.find(sig, "i=signer@example.com", 1, true) == nil then error("signature has wrong i= value") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-tables-token-2") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user3@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end if string.find(sig, "i=signer@foo.example.com", 1, true) == nil then error("signature has wrong i= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables.conf000066400000000000000000000002621337314105200253670ustar00rootroot00000000000000# # relaxed/simple signing test Background No Canonicalization relaxed/simple RequireSafeKeys No KeyTable file:t-sign-rs-tables.keys SigningTable file:t-sign-rs-tables.sign OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables.keys000066400000000000000000000000541337314105200254140ustar00rootroot00000000000000testkey example.com:test:./testkey.private OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables.lua000066400000000000000000000134201337314105200252230ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple signing test using KeyTable/SigningTable -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test using tables") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs-tables.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs-tables.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-tables") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end if string.find(sig, "i=signer@example.com", 1, true) ~= nil then error("signature has unexpected i= value") end mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs-tables") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user2@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end if string.find(sig, "i=signer@example.com", 1, true) == nil then error("signature has wrong i= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs-tables.sign000066400000000000000000000001551337314105200254030ustar00rootroot00000000000000user@example.com testkey user2@example.com testkey:signer@example.com user3@example.com testkey:signer@foo.% OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs.conf000066400000000000000000000002421337314105200241150ustar00rootroot00000000000000# # relaxed/simple signing test Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test Canonicalization relaxed/simple OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-rs.lua000066400000000000000000000063561337314105200237650ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- relaxed/simple signing test -- -- Confirms that a signature is added with the correct contents. mt.echo("*** relaxed/simple signing test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-rs.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-rs.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-rs") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=relaxed/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss000077500000000000000000000002421337314105200231750ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-all000077500000000000000000000002661337314105200237510ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test for all domains if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-all.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-all.conf000066400000000000000000000001671337314105200246720ustar00rootroot00000000000000# # simple/simple signing test Background No Domain * RequireSafeKeys No KeyFile testkey.private Selector test OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-all.lua000066400000000000000000000064561337314105200245350ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test for all domains ("Domain *" in config) -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test with 'Domain *'") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-all.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-all.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-all") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-conditional000077500000000000000000000002671337314105200255050ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest -v -v -v $MILTERTESTFLAGS -s $srcdir/t-sign-ss-conditional.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-conditional.conf000066400000000000000000000002651337314105200264240ustar00rootroot00000000000000# # simple/simple signing test Background No Domain example.com ConditionalSignatures file:t-sign-ss-conditional.cs RequireSafeKeys No KeyFile testkey.private Selector test OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-conditional.cs000066400000000000000000000000301337314105200260720ustar00rootroot00000000000000example.com:example.net OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-conditional.lua000066400000000000000000000113271337314105200262610ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2013, 2015, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-conditional.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-conditional.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-conditional") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end if mt.rcptto(conn, "user@example.net") ~= nil then error("mt.rcptto() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.rcptto() unexpected reply") end -- send headers if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end if mt.header(conn, "To", "user@example.net") ~= nil then error("mt.header(To) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(To) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties -- first the conditional signature sig = mt.getheader(conn, "DKIM-Signature", 0) mt.echo(sig) if string.find(sig, "c=simple/simple", 1, true) == nil then error("conditional signature has wrong c= value") end if string.find(sig, "v=2", 1, true) == nil then error("conditional signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("conditional signature has wrong d= value") end if string.find(sig, "!cd=example.net", 1, true) == nil then error("conditional signature has wrong !cd= value") end if string.find(sig, "s=test", 1, true) == nil then error("conditional signature has wrong s= value") end if string.find(sig, "bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=", 1, true) == nil then error("conditional signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject:To", 1, true) == nil then error("conditional signature has wrong h= value") end -- then the regular one sig = mt.getheader(conn, "DKIM-Signature", 1) if sig == nil then error("only one signature found") end mt.echo(sig) if string.find(sig, "c=simple/simple", 1, true) == nil then error("primary signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("primary signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("primary signature has wrong d= value") end if string.find(sig, "!cd=", 1, true) ~= nil then error("primary signature has a !cd= value") end if string.find(sig, "s=test", 1, true) == nil then error("primary signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("primary signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject:To", 1, true) == nil then error("primary signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-ltag000077500000000000000000000002631337314105200241250ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test with l= tag if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-ltag.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-ltag.conf000066400000000000000000000002411337314105200250420ustar00rootroot00000000000000# # simple/simple signing test with l= tag Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test BodyLengthDB csl:* OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-ltag.lua000066400000000000000000000065351337314105200247120ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple signing test with l= tag -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test with l= tag") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-ltag.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-ltag.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-ltag") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, " l=", 1, true) == nil then error("signature is missing l= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro000077500000000000000000000003131337314105200242730ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test using macro-based origin selection if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-macro.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value000077500000000000000000000003411337314105200254060ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test using macro-based origin selection with value test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-macro-value.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value-file000077500000000000000000000003771337314105200263340ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test using macro-based origin selection with value test # configured with a file if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-macro-value-file.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value-file.conf000066400000000000000000000004131337314105200272440ustar00rootroot00000000000000# # simple/simple signing test using macros to validate origin with value test # configured with a file Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test InternalHosts - MacroList file:t-sign-ss-macro-value-file.list OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value-file.list000066400000000000000000000000241337314105200272700ustar00rootroot00000000000000testmacro testvalue OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value-file.lua000066400000000000000000000071251337314105200271070ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test using macros to validate origin -- -- Confirms that a signature is added with the correct contents when the -- origin is validated via macro mt.echo("*** simple/simple signing test using macros to validate origin (file)") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-macro-value-file.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-macro-value-file.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send HELO -- if mt.helo(conn, "localhost") ~= nil then -- error("mt.helo() failed") -- end -- if mt.getreply(conn) ~= SMFIR_CONTINUE then -- error("mt.helo() unexpected reply") -- end -- send envelope macros and sender data mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-macro-value-file", "{testmacro}", "testvalue") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value.conf000066400000000000000000000003411337314105200263270ustar00rootroot00000000000000# # simple/simple signing test using macros to validate origin with value test Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test InternalHosts - MacroList testmacro=testvalue OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro-value.lua000066400000000000000000000071071337314105200261720ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test using macros to validate origin -- -- Confirms that a signature is added with the correct contents when the -- origin is validated via macro mt.echo("*** simple/simple signing test using macros to validate origin (value)") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-macro-value.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-macro-value.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send HELO -- if mt.helo(conn, "localhost") ~= nil then -- error("mt.helo() failed") -- end -- if mt.getreply(conn) ~= SMFIR_CONTINUE then -- error("mt.helo() unexpected reply") -- end -- send envelope macros and sender data mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-macro-value", "{testmacro}", "testvalue") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro.conf000066400000000000000000000003071337314105200252170ustar00rootroot00000000000000# # simple/simple signing test using macros to validate origin Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test InternalHosts - MacroList testmacro OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-macro.lua000066400000000000000000000065541337314105200250650ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test using macros to validate origin -- -- Confirms that a signature is added with the correct contents when the -- origin is validated via macro mt.echo("*** simple/simple signing test using macros to validate origin") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-macro.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-macro.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-macro", "{testmacro}", "foobar") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-replace000077500000000000000000000003101337314105200246020ustar00rootroot00000000000000#!/bin/sh # # # simple/simple signing test with header field replacement if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-replace.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-replace.conf000066400000000000000000000003031337314105200255250ustar00rootroot00000000000000# # simple/simple signing test with header field replacement Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test ReplaceRules t-sign-ss-replace.txt OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-replace.lua000066400000000000000000000064651337314105200254000ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple signing test with replacement rules -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test with From: field substring replacement") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-replace.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-replace.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-replace") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@host.example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-replace.txt000066400000000000000000000000371337314105200254230ustar00rootroot00000000000000@host.example.com @example.com OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-x000077500000000000000000000002711337314105200234440ustar00rootroot00000000000000#!/bin/sh # # simple/simple signing test requesting an "x=" tag if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-sign-ss-x.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-x.conf000066400000000000000000000002531337314105200243650ustar00rootroot00000000000000# # simple/simple signing test with SignatureTTL set Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test SignatureTTL 86400 OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss-x.lua000066400000000000000000000065371337314105200242340ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test with "x=" tag -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test with 'x=' tag") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss-x.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss-x.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss-x") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "x=", 1, true) == nil then error("signature has no x= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss.conf000066400000000000000000000002011337314105200241110ustar00rootroot00000000000000# # simple/simple signing test Background No Domain example.com RequireSafeKeys No KeyFile testkey.private Selector test OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-sign-ss.lua000066400000000000000000000063461337314105200237650ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2013, The Trusted Domain Project. -- All rights reserved. -- simple/simple signing test -- -- Confirms that a signature is added with the correct contents. mt.echo("*** simple/simple signing test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-sign-ss.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-sign-ss.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-sign-ss") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that a signature got added if not mt.eom_check(conn, MT_HDRINSERT, "DKIM-Signature") and not mt.eom_check(conn, MT_HDRADD, "DKIM-Signature") then error("no signature added") end -- confirm properties sig = mt.getheader(conn, "DKIM-Signature", 0) if string.find(sig, "c=simple/simple", 1, true) == nil then error("signature has wrong c= value") end if string.find(sig, "v=1", 1, true) == nil then error("signature has wrong v= value") end if string.find(sig, "d=example.com", 1, true) == nil then error("signature has wrong d= value") end if string.find(sig, "s=test", 1, true) == nil then error("signature has wrong s= value") end if string.find(sig, "bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=", 1, true) == nil then error("signature has wrong bh= value") end if string.find(sig, "h=From:Date:Subject", 1, true) == nil then error("signature has wrong h= value") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-double-from000077500000000000000000000002641337314105200253330ustar00rootroot00000000000000#!/bin/sh # # test a message with two From: fields if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-double-from.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-double-from.conf000066400000000000000000000001301337314105200262440ustar00rootroot00000000000000# double-From: test Background No On-BadSignature reject StrictHeaders Yes Mode v OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-double-from.lua000066400000000000000000000073241337314105200261140ustar00rootroot00000000000000-- Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. -- double-From: test -- -- Confirms that an message with two From: fields TEMPFAILs mt.echo("*** double From: field") -- try to start the filter if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-double-from.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-double-from.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end mt.set_timeout(300) -- mt.sleep(15) -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "unspec") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-double-from") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.header(conn, "From", "user@example.net") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end -- syntax error in signature -- doesn't get processed until eoh though this could change later if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1283905216; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=AiGrvHu2mODRK2BlLXJy/YjCiBg3qr/QZ7laVq7ccMeA2QDmrksc9Hoj7lsFQc+bs\r\n\t lgIJh+8gzyQeGZz8TYX/LJaBg8kH8jn0w70hvI63sgN4wytwhvpvkPInUhLXgpkknj\r\n\t DT70LzX2ABd24nHDshfS22v+nwUl9xuMAq77UtbE=") ~= nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_SKIP then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end -- verify that a DKIM pass result was added n = 0 found = 0 while true do ar = mt.getheader(conn, "Authentication-Results", n) if ar == nil then break end if string.find(ar, "dkim=permerror", 1, true) ~= nil then found = 1 break end n = n + 1 end if found == 0 then error("incorrect DKIM result") end if n > 1 then error("too many Authentication-Results fields") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-malformed000077500000000000000000000002531337314105200250640ustar00rootroot00000000000000#!/bin/sh # # # malformed From: field test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-malformed.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-malformed.conf000066400000000000000000000002221337314105200260010ustar00rootroot00000000000000# malformed From: field verifying test Background No Mode v KeyTable file:t-sign-rs-multiple.keys SigningTable file:t-sign-rs-multiple.sign OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-malformed.lua000066400000000000000000000055151337314105200256470ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- malformed From: field message test -- -- Confirms that an unsigned message produces the correct result mt.echo("*** malformed From: field message") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-malformed.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-malformed.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-malformed") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_SKIP and mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that the right Authentication-Results header field got added if mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") or mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then ar = mt.getheader(conn, "Authentication-Results", 0) if string.find(ar, "format", 1, true) == nil then error("incorrect Authentication-Results field") end else error("missing Authentication-Results field") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-report000077500000000000000000000006371337314105200244370ustar00rootroot00000000000000#!/bin/sh # # # verify reporting of failed signatures if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi export TMPFILE=`mktemp /tmp/opendkim-XXXXXXXXX` ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-report.lua || exit 1 # ignore version differences in useragent and arrival date diff -I ^User-Agent -I ^Arrival-Date -I ^Date \ -u $srcdir/t-verify-report.txt ${TMPFILE} || exit 1 rm -f ${TMPFILE} OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-report.conf000066400000000000000000000004631337314105200253550ustar00rootroot00000000000000# # simple/simple verifying test with report generation Background No Mode v TestPublicKeys pubkeys TestDNSData file:pubkeys SendReports yes ReportAddress "Mail Admin" ReportBccAddress postmaster@example.net, tom@example.net, "hary" MTACommand ./testmta OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-report.lua000066400000000000000000000075401337314105200252140ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- reporting key verify test -- -- Confirms that a report is sent when the verification fails mt.echo("*** test reporting of failed signatures occurs") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-report.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-report.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send HELO unles it was negotiated out if not mt.test_option(conn, SMFIP_NOHELO) then if mt.helo(conn, "localhost") ~= nil then error("mt.helo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.helo() unexpected reply") end end -- send envelope macros and sender data mt.macro(conn, SMFIC_MAIL, "i", "t-verify-report") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\n\tt=1329113412; r=y; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\n\th=From:Date:Subject;\n\tb=J4DYccKlZx8+EFXvnUEZyiQn2JNpQ0JSvTT1PeyGfrYPAux//SHXb/K/Z6jYzqH5z\n\t ZkiQ5UutfDjkkW2WsRCilkvodnp0PGrLK5fDFHBK7vGTLzXyhI/zubkeYVZufd+9U7\n\t kuVE9jz2Vb4YDL8DC9EZJ5SyAY8uNnsrky8gQ948=") ~= nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@ex4mple.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end if mt.header(conn, "Message-ID", "<184510.abcdefg@example.com>") ~= nil then error("mt.header(Message-ID) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Message-ID) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end ar = mt.getheader(conn, "Authentication-Results", 0) if string.find(ar, "dkim=fail", 1, true) == nil then print(ar) error("incorrect DKIM result") end if string.find(ar, "verification failed", 1, true) == nil then print(ar) error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-report.txt000066400000000000000000000042001337314105200252400ustar00rootroot00000000000000-t -fpostmaster@example.org From: "Mail Admin" To: dkim-feedbacks@example.com Bcc: postmaster@example.net, tom@example.net, "hary" Subject: DKIM failure report for t-verify-report MIME-Version: 1.0 Content-Type: multipart/report; report-type=feedback-report; boundary="dkimreport/unknown-host/t-verify-report" --dkimreport/unknown-host/t-verify-report Content-Type: text/plain DKIM failure report for job t-verify-report on unknown-host The canonicalized form of the failed message's header and body are attached. --dkimreport/unknown-host/t-verify-report Content-Type: message/feedback-report User-Agent: OpenDKIM-Filter/2.3.1 Version: 0.1 Original-Envelope-Id: t-verify-report Original-Mail-From: user@example.com Reporting-MTA: unknown-host Source-IP: 127.0.0.1 Message-ID: <184510.abcdefg@example.com> Arrival-Date: Mon, 14 Mar 2011 16:41:35 -0700 Reported-Domain: example.com Delivery-Result: other Feedback-Type: auth-failure Auth-Failure: signature (signature verification failed) DKIM-Failure: signature DKIM-Domain: example.com DKIM-Selector: test DKIM-Identity: @example.com DKIM-Canonicalized-Header: RnJvbTogdXNlckBleDRtcGxlLmNvbQ0KRGF0ZTogVHVl LCAyMiBEZWMgMjAwOSAxMzowNDoxMiAtMDgwMA0KU3ViamVjdDogU2lnbmluZyB0ZXN0 DQpES0lNLVNpZ25hdHVyZTogdj0xOyBhPXJzYS1zaGEyNTY7IGM9c2ltcGxlL3NpbXBs ZTsgZD1leGFtcGxlLmNvbTsgcz10ZXN0Ow0KCXQ9MTMyOTExMzQxMjsgcj15OyBiaD0z VldHUUdZK2NTTllkMU1HTStYNmhSWFUwc3RsOEpDYVF0bDRtYlgvajJJPTsNCgloPUZy b206RGF0ZTpTdWJqZWN0Ow0KCWI9 DKIM-Canonicalized-Body: VGhpcyBpcyBhIHRlc3QhDQo= --dkimreport/unknown-host/t-verify-report Content-Type: text/rfc822-headers DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test; t=1329113412; r=y; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=; h=From:Date:Subject; b=J4DYccKlZx8+EFXvnUEZyiQn2JNpQ0JSvTT1PeyGfrYPAux//SHXb/K/Z6jYzqH5z ZkiQ5UutfDjkkW2WsRCilkvodnp0PGrLK5fDFHBK7vGTLzXyhI/zubkeYVZufd+9U7 kuVE9jz2Vb4YDL8DC9EZJ5SyAY8uNnsrky8gQ948= From: user@ex4mple.com Date: Tue, 22 Dec 2009 13:04:12 -0800 Subject: Signing test Message-ID: <184510.abcdefg@example.com> --dkimreport/unknown-host/t-verify-report-- OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-revoked000077500000000000000000000002571337314105200245610ustar00rootroot00000000000000#!/bin/sh # # # verify revoked key test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-revoked.lua -v -v -v OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-revoked.conf000066400000000000000000000001411337314105200254720ustar00rootroot00000000000000# simple/simple verifying test with revoked key Background No Mode v TestPublicKeys pubkeys OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-revoked.lua000066400000000000000000000067711337314105200253450ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- revoked key verify test -- -- Confirms that a signature matching a revoked key is reported as such mt.echo("*** simple/simple verify revoked key") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-revoked.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-revoked.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-revoked") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=example.com; s=revoked;\n\th=domainkey-signature:mime-version:received:received:in-reply-to:\n\t references:date:message-id:subject:from:to:cc:content-type;\n\tbh=34lkc8Kvp/4C7BZOHlFJr8XlPeQt1pLHo4V8JljV13c=;\n\tb=sF59xX14kHxUUF2NQs1sF7Jla+dfLKwqCkYRFfLAo1n48oRvlcc3W1nwWU/BEk6mp9\n\t 0ZoylqVfErDrxDTeAEDLwaaPSL+4ZMjvp3WZyuFp2gCoQb5U8INu+vdnNvAgr4hi1Ku4\n\t mEQhR5ncoCxOUWq4e7r1CCIH4DM2fLbZa4ywQ=") ~= nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end ar = mt.getheader(conn, "Authentication-Results", 0) if string.find(ar, "dkim=fail", 1, true) == nil then error("incorrect DKIM result") end if string.find(ar, "revoked", 1, true) == nil then error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss000077500000000000000000000002641337314105200235450ustar00rootroot00000000000000#!/bin/sh # # # simple/simple verifying test (should pass) if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-ss.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-ar-bad000077500000000000000000000003451337314105200246710ustar00rootroot00000000000000#!/bin/sh # # simple/simple verifying test with oversized Authentication-Results (should # not crash) if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-ss-ar-bad.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-ar-bad.conf000066400000000000000000000002431337314105200256070ustar00rootroot00000000000000# simple/simple verifying test with oversized Authentication-Results (should # not crash) TestPublicKeys pubkeys Mode v On-BadSignature reject Background No OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-ar-bad.lua000066400000000000000000000075161337314105200254550ustar00rootroot00000000000000-- Copyright (c) 2009-2014, The Trusted Domain Project. All rights reserved. -- simple/simple verifying test with oversized Authentication-Results (should -- not crash) mt.echo("*** simple/simple verifying with oversized Authentication-Results") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-ss-ar-bad.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-ss-ar-bad.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-ar-bad") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end ar = "se01.i.sendmail-inc.jp;" for n = 1, 90 do ar = ar .. " spf=pass;" if n % 5 == 0 then ar = ar .. "\n\t" end end if mt.header(conn, "Authentication-Results", ar) ~= nil then error("mt.header(Authentication-Results) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Authentication-Results) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end -- verify that a DKIM pass result was added n = 0 found = 0 while true do ar = mt.getheader(conn, "Authentication-Results", n) if ar == nil then break end if string.find(ar, "dkim=pass", 1, true) ~= nil then found = 1 break end n = n + 1 end if found == 0 then error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-atps000077500000000000000000000002771337314105200245160ustar00rootroot00000000000000#!/bin/sh # # # simple/simple verifying test with an ATPS result if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-ss-atps.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-atps.conf000066400000000000000000000002141337314105200254260ustar00rootroot00000000000000# simple/simple verifying test with ATPS TestPublicKeys pubkeys TestDNSData file:pubkeys Mode v On-BadSignature reject Background No OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-atps.lua000066400000000000000000000073231337314105200252720ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple verify test with ATPS -- -- Confirms that a message with a valid signature passes and an ATPS result -- is recorded mt.echo("*** simple/simple verifying test with ATPS") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-ss-atps.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-ss-atps.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-atps") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=relaxed/simple; d=example.com; s=test;\r\n\tt=1325791961; atpsh=sha256; atps=example.net;\r\n\tbh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=HWU4M/8p+s8ysNCuKbatRvuPiU399Fip1Avl+tQnybes9P/9lr0B9MdT7FfT9XG0s\r\n\t F3gW4k6MlDjomVuJ10jizT+ubmzn2fz4vHDSPonb1sl9keAhSG0xHpUpZw2loJs0iS\r\n\t y9Hd9fV7iSO3NMdrzz2wM/n1S3b2ckjpiG/qxp9E=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.net") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end -- verify that a DKIM pass result was added n = 0 passfound = 0 atpsfound = 0 while true do ar = mt.getheader(conn, "Authentication-Results", n) if ar == nil then break end if string.find(ar, "dkim=pass", 1, true) ~= nil then passfound = 1 end if string.find(ar, "dkim-atps=pass", 1, true) ~= nil then atpsfound = 1 end n = n + 1 end if passfound == 0 then error("incorrect/missing DKIM result") end if atpsfound == 0 then error("incorrect/missing ATPS result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-bad000077500000000000000000000002701337314105200242660ustar00rootroot00000000000000#!/bin/sh # # # simple/simple verifying test (should fail) if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-ss-bad.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-bad.conf000066400000000000000000000001661337314105200252130ustar00rootroot00000000000000# simple/simple verifying test (should fail) TestPublicKeys pubkeys Mode v On-BadSignature reject Background No OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-bad.lua000066400000000000000000000056701337314105200250540ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple verify test (should fail) -- -- Confirms that a message with an invalid signature is rejected mt.echo("*** simple/simple verifying test (bad)") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-ss-bad.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-ss-bad.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-bad") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1283905216; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=AiGrvHu2mODRK2BlLXJy/YjCiBg3qr/QZ7laVq7ccMeA2QDmrksc9Hoj7lsFQc+bs\r\n\t lgIJh+8gzyQeGZz8TYX/LJaBg8kH8jn0w70hvI63sgN4wytwhvpvkPInUhLXgpkknj\r\n\t DT70LzX2ABd24nHDshfS22v+nwUl9xuMAq77UtbE=") ~= nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.net") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_REPLYCODE then error("mt.eom() unexpected reply") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-header-fields000077500000000000000000000003351337314105200262360ustar00rootroot00000000000000#!/bin/sh # # # simple/simple test verifying header.x fields are present (should pass) if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-ss-header-fields.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-header-fields.conf000066400000000000000000000002221337314105200271520ustar00rootroot00000000000000# simple/simple test verifying header.x fields are present (should pass) TestPublicKeys pubkeys Mode v On-BadSignature reject Background No OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-header-fields.lua000066400000000000000000000076421337314105200270230ustar00rootroot00000000000000-- Copyright (c) 2017, The Trusted Domain Project. All rights reserved. -- simple/simple test verifying header.x fields are present (should pass) -- -- Confirms that a message with a valid signature has all AR header.X fields mt.echo("*** simple/simple test verifying header.x fields are present (good)") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-ss-header-fields.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-ss-header-fields.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-header-fields") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end -- verify that a DKIM pass result was added n = 0 found = 0 while true do ar = mt.getheader(conn, "Authentication-Results", n) if ar == nil then break end if string.find(ar, "dkim=pass", 1, true) ~= nil then found = 1 break end if string.find(ar, "header.d=example.com", 1, true) ~= nil then found = 1 break end if string.find(ar, "header.s=test", 1, true) ~= nil then found = 1 break end if string.find(ar, "header.i=@example.com", 1, true) ~= nil then found = 1 break end if string.find(ar, "header.b=RNAhx6cV", 1, true) ~= nil then found = 1 break end n = n + 1 end if found == 0 then error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-rep000077500000000000000000000003011337314105200243210ustar00rootroot00000000000000#!/bin/sh # # # simple/simple verifying test with reputation checks if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-ss-rep.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-rep.conf000066400000000000000000000003711337314105200252510ustar00rootroot00000000000000# simple/simple verifying test with reputation checks TestPublicKeys pubkeys Mode v On-BadSignature reject Background No ReputationLimits csl:*=72 ReputationRatios csl:*=0.5 ReputationTimeFactor 24 ReputationSpamCheck /^X-Spam: ?[Yy][Ee][Ss]/ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss-rep.lua000066400000000000000000000247731337314105200251210ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple verify test with reputation checks -- -- Exercises the reputation system mt.echo("*** simple/simple verifying test with reputation checks") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-ss-rep.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-ss-rep.conf", "-p", sock) --- CONNECTION #1, MESSAGE #1 -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.2") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-rep") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end mt.disconnect(conn) --- CONNECTION #2, MESSAGE #2 -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.2") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-rep") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end if mt.header(conn, "X-Spam", "Yes") ~= nil then error("mt.header(X-Spam) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(X-Spam) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end mt.disconnect(conn) --- CONNECTION #3, MESSAGE #3 -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.2") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-rep") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end if mt.header(conn, "X-Spam", "Yes") ~= nil then error("mt.header(X-Spam) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(X-Spam) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_TEMPFAIL and mt.getreply(conn) ~= SMFIR_REPLYCODE then error("mt.eom() unexpected reply") end mt.disconnect(conn) --- CONNECTION #4, MESSAGE #4 -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.2") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss-rep") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss.conf000066400000000000000000000001661337314105200244670ustar00rootroot00000000000000# simple/simple verifying test (should pass) TestPublicKeys pubkeys Mode v On-BadSignature reject Background No OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-ss.lua000066400000000000000000000067201337314105200243250ustar00rootroot00000000000000-- Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. -- simple/simple verify test (should pass) -- -- Confirms that a message with a valid signature passes mt.echo("*** simple/simple verifying test (good)") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-ss.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-ss.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-ss") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "DKIM-Signature", "v=1; a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1296710324; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=RNAhx6cV5AeZWJDEJG1hROdvCukhJnokhI9oABHwAyUAzC6MDntoH4PrS2jS7HGw2\r\n\t D7pU4yLGrlNsGlK8JvqizYNHl+v9+B6OnWAgzkgTimWTqBCYwo8X01N6hqoXDAm8hC\r\n\t RUpmeJvC84K5/nHHLASCb4W1PC2R4VkxUoyVnlYE=") ~=nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end -- verify that a DKIM pass result was added n = 0 found = 0 while true do ar = mt.getheader(conn, "Authentication-Results", n) if ar == nil then break end if string.find(ar, "dkim=pass", 1, true) ~= nil then found = 1 break end n = n + 1 end if found == 0 then error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-syntax000077500000000000000000000002561337314105200244470ustar00rootroot00000000000000#!/bin/sh # # # unspecified protocol family test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-syntax.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-syntax.conf000066400000000000000000000001171337314105200253640ustar00rootroot00000000000000# bad signature protocol test Background No On-BadSignature reject Mode v OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-syntax.lua000066400000000000000000000052041337314105200252220ustar00rootroot00000000000000-- Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. -- Syntax error proccessing test -- -- Confirms that an message with a syntax error TEMPFAILs mt.echo("*** syntax error in DKIM signature") -- try to start the filter if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-syntax.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-syntax.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "unspec") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-syntax") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end -- syntax error in signature -- doesn't get processed until eoh though this could change later if mt.header(conn, "DKIM-Signature", "v=1 a=rsa-sha256; c=simple/simple; d=example.com; s=test;\r\n\tt=1283905216; bh=3VWGQGY+cSNYd1MGM+X6hRXU0stl8JCaQtl4mbX/j2I=;\r\n\th=From:Date:Subject;\r\n\tb=AiGrvHu2mODRK2BlLXJy/YjCiBg3qr/QZ7laVq7ccMeA2QDmrksc9Hoj7lsFQc+bs\r\n\t lgIJh+8gzyQeGZz8TYX/LJaBg8kH8jn0w70hvI63sgN4wytwhvpvkPInUhLXgpkknj\r\n\t DT70LzX2ABd24nHDshfS22v+nwUl9xuMAq77UtbE=") ~= nil then error("mt.header(DKIM-Signature) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(DKIM-Signature) unexpected reply") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_REPLYCODE then error("mt.eoh() unexpected reply - expected REPLYCODE (reject)") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unsigned000077500000000000000000000002451337314105200247330ustar00rootroot00000000000000#!/bin/sh # # # unsigned message test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-unsigned.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unsigned-silent000077500000000000000000000002631337314105200262270ustar00rootroot00000000000000#!/bin/sh # # # silent unsigned message test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-unsigned-silent.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unsigned-silent.conf000066400000000000000000000001041337314105200271420ustar00rootroot00000000000000# unsigned message verifying test (silent) Background No Mode v OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unsigned-silent.lua000066400000000000000000000052751337314105200270140ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- unsigned message test (silent) -- -- Confirms that an unsigned message produces the correct result mt.echo("*** unsigned message (silent)") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-ver-unsigned-silent.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-unsigned-silent.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-unsigned-silent") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_SKIP and mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that no Authentication-Results header field got added if mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") or mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("Authentication-Results added") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unsigned.conf000066400000000000000000000001221337314105200256460ustar00rootroot00000000000000# unsigned message verifying test Background No Mode v AlwaysAddARHeader True OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unsigned.lua000066400000000000000000000056551337314105200255220ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- unsigned message test -- -- Confirms that an unsigned message produces the correct result mt.echo("*** unsigned message") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-unsigned.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-unsigned.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "127.0.0.1") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-unsigned") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_SKIP and mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end -- verify that an Authentication-Results header field got added if not mt.eom_check(conn, MT_HDRINSERT, "Authentication-Results") and not mt.eom_check(conn, MT_HDRADD, "Authentication-Results") then error("no Authentication-Results added") end ar = mt.getheader(conn, "Authentication-Results", 0) if string.find(ar, "unknown-host;", 1, true) == nil then error("missing authservid in Authentication-Results field") end if string.find(ar, "dkim=none", 1, true) == nil then error("incorrect DKIM result") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unspec000077500000000000000000000002561337314105200244160ustar00rootroot00000000000000#!/bin/sh # # # unspecified protocol family test if [ x"$srcdir" = x"" ] then srcdir=`pwd` fi ../../miltertest/miltertest $MILTERTESTFLAGS -s $srcdir/t-verify-unspec.lua OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unspec.conf000066400000000000000000000000651337314105200253350ustar00rootroot00000000000000# unspecified protocol test Background No Mode v OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/t-verify-unspec.lua000066400000000000000000000047001337314105200251710ustar00rootroot00000000000000-- Copyright (c) 2009, 2010, 2012, 2013, The Trusted Domain Project. -- All rights reserved. -- unspecified protocol family test -- -- Confirms that an unsigned message produces the correct result mt.echo("*** unspecified protocol family test") -- setup if TESTSOCKET ~= nil then sock = TESTSOCKET else sock = "unix:" .. mt.getcwd() .. "/t-verify-unspec.sock" end binpath = mt.getcwd() .. "/.." if os.getenv("srcdir") ~= nil then mt.chdir(os.getenv("srcdir")) end -- try to start the filter mt.startfilter(binpath .. "/opendkim", "-x", "t-verify-unspec.conf", "-p", sock) -- try to connect to it conn = mt.connect(sock, 40, 0.25) if conn == nil then error("mt.connect() failed") end -- send connection information -- mt.negotiate() is called implicitly if mt.conninfo(conn, "localhost", "unspec") ~= nil then error("mt.conninfo() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.conninfo() unexpected reply") end -- send envelope macros and sender data -- mt.helo() is called implicitly mt.macro(conn, SMFIC_MAIL, "i", "t-verify-unsigned") if mt.mailfrom(conn, "user@example.com") ~= nil then error("mt.mailfrom() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.mailfrom() unexpected reply") end -- send headers -- mt.rcptto() is called implicitly if mt.header(conn, "From", "user@example.com") ~= nil then error("mt.header(From) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(From) unexpected reply") end if mt.header(conn, "Date", "Tue, 22 Dec 2009 13:04:12 -0800") ~= nil then error("mt.header(Date) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Date) unexpected reply") end if mt.header(conn, "Subject", "Signing test") ~= nil then error("mt.header(Subject) failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.header(Subject) unexpected reply") end -- send EOH if mt.eoh(conn) ~= nil then error("mt.eoh() failed") end if mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.eoh() unexpected reply") end -- send body if mt.bodystring(conn, "This is a test!\r\n") ~= nil then error("mt.bodystring() failed") end if mt.getreply(conn) ~= SMFIR_SKIP and mt.getreply(conn) ~= SMFIR_CONTINUE then error("mt.bodystring() unexpected reply") end -- end of message; let the filter react if mt.eom(conn) ~= nil then error("mt.eom() failed") end if mt.getreply(conn) ~= SMFIR_ACCEPT then error("mt.eom() unexpected reply") end mt.disconnect(conn) OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/testkey.private000066400000000000000000000015671337314105200245220ustar00rootroot00000000000000-----BEGIN RSA PRIVATE KEY----- MIICXQIBAAKBgQC9p5rp5EjC8cZbnlUpasA5HoUYwSA+HEBsBZnxppmehsiCLY/r SGDxmYaOL2LhGJur4UnXzTRpB/VgPTNOn3bkudEARqu0H2W6afEcI46igMs8fuZl yIi+UMGdUbn5tgbTRS7g6r9bxOcxwTtZcKAhvCWfDiTc2QeEzzxxyL4jewIDAQAB AoGAJlOEntefTKYHa+RnWWNVTTW5t/LvTR3wduP65DbCvKKISqZiey25SZm482ro FI0giG+SuKWjfcY59CTqBW18XQrN3PmYAKfL6yOOA5jb7yEOqQWIC77amUvBJ1CQ 5HDHT/L18E1K7A92lmS4FV94r8Qu9yWMOCdW7+vKO8HcTiECQQD7JYh45YSceDSU kHIPpCQhGXvGPhB2sp5beP13zVYtXYq5bBape9iMgD80Ql0swCdK5C8d/H0WUygC WH9IXYuFAkEAwVHcU+bsyjQ2SI8mHiGLWBUkxGOmcpLuvQawrGFK0VhRPStWmh38 t9kwCCtvA4GqPy2UWFE+DvUrV2cWYA6i/wJBAPEDsvU6Zcn2/Za5DA0Am398QjEc LJaMkbX85VoMHzCH/XI2TYU2iblD9ePD8EDa4ppXYvQm8y/ye4nMvdGHnDUCQQCp pROLET/EJdNpEy2pDVjBoDRWnvgG3Ufh20gYzXwhf7YyzqA9uIj4MQCEetD9q8Dh ljby1cB20dEJ7y3kd5OzAkBfhe+7Yj1vqJbbiL4l7AEVoJ06scnnRS3P8XQaMxY3 29G3iZoC/+P7Si1hQZKj7GhmDpY/4fkocOQ5l9ufaeKt -----END RSA PRIVATE KEY----- OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/tests/testmta000077500000000000000000000003441337314105200230350ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2010, 2012, The Trusted Domain Project. All rights reserved. # # Dummy "MTA" that just writes stdin to a file for testing. while [ "$1" != "" ]; do echo $1 >> $TMPFILE shift done cat >> $TMPFILE OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/util.c000066400000000000000000001016431337314105200214110ustar00rootroot00000000000000/* ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009-2015, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef _FFR_REPLACE_RULES # include #endif /* _FFR_REPLACE_RULES */ #ifdef HAVE_PATHS_H # include #endif /* HAVE_PATHS_H */ #ifndef _PATH_DEVNULL # define _PATH_DEVNULL "/dev/null" #endif /* ! _PATH_DEVNULL */ #ifdef SOLARIS # if SOLARIS <= 20600 # define socklen_t size_t # endif /* SOLARIS <= 20600 */ #endif /* SOLARIS */ /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* opendkim includes */ #include "opendkim.h" #include "util.h" #include "opendkim-db.h" /* macros */ #define DEFARGS 8 /* missing definitions */ #ifndef INADDR_NONE # define INADDR_NONE ((uint32_t) -1) #endif /* ! INADDR_NONE */ /* globals */ #ifdef POPAUTH static pthread_mutex_t pop_lock; #endif /* POPAUTH */ static char *optlist[] = { #if DEBUG "DEBUG", #endif /* DEBUG */ #if POPAUTH "POPAUTH", #endif /* POPAUTH */ #if QUERY_CACHE "QUERY_CACHE", #endif /* QUERY_CACHE */ #if USE_DB "USE_DB", #endif /* USE_DB */ #if USE_ERLANG "USE_ERLANG", #endif /* USE_ERLANG */ #if USE_JANSSON "USE_JANSSON", #endif /* USE_JANSSON */ #if USE_LDAP "USE_LDAP", #endif /* USE_LDAP */ #if USE_LUA "USE_LUA", #endif /* USE_LUA */ #if USE_MDB "USE_MDB", #endif /* USE_MDB */ #if USE_ODBX "USE_ODBX", #endif /* USE_ODBX */ #if USE_UNBOUND "USE_UNBOUND", #endif /* USE_UNBOUND */ #ifdef _FFR_ADSP_LISTS "_FFR_ADSP_LISTS", #endif /* _FFR_ADSP_LISTS */ #ifdef _FFR_ATPS "_FFR_ATPS", #endif /* _FFR_ATPS */ #ifdef _FFR_CONDITIONAL "_FFR_CONDITIONAL", #endif /* _FFR_CONDITIONAL */ #ifdef _FFR_DEFAULT_SENDER "_FFR_DEFAULT_SENDER", #endif /* _FFR_DEFAULT_SENDER */ #if _FFR_DIFFHEADERS "_FFR_DIFFHEADERS", #endif /* _FFR_DIFFHEADERS */ #if _FFR_IDENTITY_HEADER "_FFR_IDENTITY_HEADER", #endif /* _FFR_IDENTITY_HEADER */ #if _FFR_LDAP_CACHING "_FFR_LDAP_CACHING", #endif /* _FFR_LDAP_CACHING */ #if _FFR_LUA_ONLY_SIGNING "_FFR_LUA_ONLY_SIGNING", #endif /* _FFR_LUA_ONLY_SIGNING */ #if _FFR_POSTGRESQL_RECONNECT_HACK "_FFR_POSTGRESQL_RECONNECT_HACK", #endif /* _FFR_POSTGRESQL_RECONNECT_HACK */ #if _FFR_RATE_LIMIT "_FFR_RATE_LIMIT", #endif /* _FFR_RATE_LIMIT */ #if _FFR_RBL "_FFR_RBL", #endif /* _FFR_RBL */ #if _FFR_REPLACE_RULES "_FFR_REPLACE_RULES", #endif /* _FFR_REPLACE_RULES */ #if _FFR_REPRRD "_FFR_REPRRD", #endif /* _FFR_REPRRD */ #if _FFR_REPUTATION "_FFR_REPUTATION", #endif /* _FFR_REPUTATION */ #if _FFR_RESIGN "_FFR_RESIGN", #endif /* _FFR_RESIGN */ #if _FFR_SENDER_MACRO "_FFR_SENDER_MACRO", #endif /* _FFR_SENDER_MACRO */ #ifdef _FFR_SOCKETDB "_FFR_SOCKETDB", #endif /* _FFR_SOCKETDB */ #if _FFR_STATS "_FFR_STATS", #endif /* _FFR_STATS */ #if _FFR_STATSEXT "_FFR_STATSEXT", #endif /* _FFR_STATSEXT */ #if _FFR_VBR "_FFR_VBR", #endif /* _FFR_VBR */ NULL }; /* struct dkimf_dstring -- a dynamically-sized string */ struct dkimf_dstring { int ds_alloc; int ds_max; int ds_len; u_char * ds_buf; }; /* base64 alphabet */ static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /* ** DKIMF_ISBLANK -- return TRUE iff a string contains only whitespace ** ** Parameters: ** str -- string to check ** ** Return value: ** TRUE if "str" is either zero-length or contains only whitespace */ _Bool dkimf_isblank(char *str) { char *p; for (p = str; *p != '\0'; p++) { if (isascii(*p) && isspace(*p)) continue; return FALSE; } return TRUE; } /* ** DKIMF_OPTLIST -- print active FFRs ** ** Parameters: ** where -- where to write the list ** ** Return value: ** None. */ void dkimf_optlist(FILE *where) { _Bool first = TRUE; int c; assert(where != NULL); for (c = 0; optlist[c] != NULL; c++) { if (first) { fprintf(where, "\tActive code options:\n"); first = FALSE; } fprintf(where, "\t\t%s\n", optlist[c]); } fprintf(where, "\t%s\n", LIBOPENDKIM_FEATURE_STRING); } /* ** DKIMF_SETMAXFD -- increase the file descriptor limit as much as possible ** ** Parameters: ** None. ** ** Return value: ** None. */ void dkimf_setmaxfd(void) { struct rlimit rlp; if (getrlimit(RLIMIT_NOFILE, &rlp) != 0) { syslog(LOG_WARNING, "getrlimit(): %s", strerror(errno)); } else { rlp.rlim_cur = rlp.rlim_max; if (setrlimit(RLIMIT_NOFILE, &rlp) != 0) { syslog(LOG_WARNING, "setrlimit(): %s", strerror(errno)); } } } /* ** DKIMF_STRIPBRACKETS -- remove angle brackets from the sender address ** ** Parameters: ** addr -- address to be processed ** ** Return value: ** None. */ void dkimf_stripbrackets(char *addr) { char *p, *q; assert(addr != NULL); p = addr; q = addr + strlen(addr) - 1; while (*p == '<' && *q == '>') { p++; *q-- = '\0'; } if (p != addr) { for (q = addr; *p != '\0'; p++, q++) *q = *p; *q = '\0'; } } /* ** DKIMF_LOWERCASE -- lowercase-ize a string ** ** Parameters: ** str -- string to convert ** ** Return value: ** None. */ void dkimf_lowercase(u_char *str) { u_char *p; assert(str != NULL); for (p = str; *p != '\0'; p++) { if (isascii(*p) && isupper(*p)) *p = tolower(*p); } } /* ** DKIMF_CHECKHOST -- check the peerlist for a host and its wildcards ** ** Parameters: ** db -- DB of records to check ** host -- hostname to find ** ** Return value: ** TRUE if there's a match, FALSE otherwise. */ _Bool dkimf_checkhost(DKIMF_DB db, char *host) { _Bool exists; int status; char *p; char buf[BUFRSZ + 1]; assert(host != NULL); /* short circuits */ if (db == NULL || host[0] == '\0') return FALSE; /* iterate over the possibilities */ for (p = host; p != NULL; p = strchr(p + 1, '.')) { /* try the negative case */ snprintf(buf, sizeof buf, "!%s", p); exists = FALSE; status = dkimf_db_get(db, buf, 0, NULL, 0, &exists); if (status != 0) return FALSE; else if (exists) return FALSE; /* ...and now the positive case */ exists = FALSE; status = dkimf_db_get(db, &buf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; } return FALSE; } /* ** DKIMF_CHECKIP -- check a peerlist table for an IP address or its matching ** wildcards ** ** Parameters: ** db -- db to check ** ip -- IP address to find ** ** Return value: ** TRUE if there's a match, FALSE otherwise. */ _Bool dkimf_checkip(DKIMF_DB db, struct sockaddr *ip) { _Bool exists; char ipbuf[DKIM_MAXHOSTNAMELEN + 1]; assert(ip != NULL); /* short circuit */ if (db == NULL) return FALSE; #if AF_INET6 if (ip->sa_family == AF_INET6) { int status; int bits; size_t dst_len; size_t iplen; char *dst; struct sockaddr_in6 sin6; struct in6_addr addr; memcpy(&sin6, ip, sizeof sin6); memcpy(&addr, &sin6.sin6_addr, sizeof addr); memset(ipbuf, '\0', sizeof ipbuf); ipbuf[0] = '!'; dst = &ipbuf[1]; dst_len = sizeof ipbuf - 1; inet_ntop(AF_INET6, &addr, dst, dst_len); dkimf_lowercase((u_char *) dst); iplen = strlen(dst); exists = FALSE; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; /* try it with square brackets */ memmove(&ipbuf[2], &ipbuf[1], iplen + 1); ipbuf[1] = '['; ipbuf[iplen + 2] = ']'; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; /* iterate over possible bitwise expressions */ for (bits = 0; bits <= 128; bits++) { size_t sz; /* try this one */ memset(ipbuf, '\0', sizeof ipbuf); ipbuf[0] = '!'; dst = &ipbuf[1]; dst_len = sizeof ipbuf - 1; inet_ntop(AF_INET6, &addr, dst, dst_len); dkimf_lowercase((u_char *) dst); iplen = strlen(dst); sz = strlcat(ipbuf, "/", sizeof ipbuf); if (sz >= sizeof ipbuf) return FALSE; dst = &ipbuf[sz]; dst_len = sizeof ipbuf - sz; sz = snprintf(dst, dst_len, "%d", 128 - bits); if (sz >= sizeof ipbuf) return FALSE; exists = FALSE; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; else if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; else if (exists) return TRUE; /* try it with square brackets */ memmove(&ipbuf[2], &ipbuf[1], iplen + 1); ipbuf[1] = '['; ipbuf[iplen + 2] = ']'; ipbuf[iplen + 3] = '\0'; sz = strlcat(ipbuf, "/", sizeof ipbuf); if (sz >= sizeof ipbuf) return FALSE; dst = &ipbuf[sz]; dst_len = sizeof ipbuf - sz; sz = snprintf(dst, dst_len, "%d", 128 - bits); if (sz >= sizeof ipbuf) return FALSE; exists = FALSE; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; /* flip off a bit */ if (bits != 128) { int idx; int bit; idx = 15 - (bits / 8); bit = bits % 8; addr.s6_addr[idx] &= ~(1 << bit); } } } #endif /* AF_INET6 */ if (ip->sa_family == AF_INET) { _Bool exists; int c; int status; int bits; size_t iplen; struct in_addr addr; struct in_addr mask; struct sockaddr_in sin; memcpy(&sin, ip, sizeof sin); memcpy(&addr.s_addr, &sin.sin_addr, sizeof addr.s_addr); /* try the IP address directly */ exists = FALSE; ipbuf[0] = '!'; (void) dkimf_inet_ntoa(addr, &ipbuf[1], sizeof ipbuf - 1); status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; /* try it with square brackets */ memmove(&ipbuf[2], &ipbuf[1], strlen(&ipbuf[1]) + 1); ipbuf[1] = '['; ipbuf[strlen(ipbuf)] = ']'; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; /* iterate over possible bitwise expressions */ for (bits = 32; bits >= 0; bits--) { if (bits == 32) { mask.s_addr = 0xffffffff; } else { mask.s_addr = 0; for (c = 0; c < bits; c++) mask.s_addr |= htonl(1 << (31 - c)); } addr.s_addr = addr.s_addr & mask.s_addr; memset(ipbuf, '\0', sizeof ipbuf); ipbuf[0] = '!'; (void) dkimf_inet_ntoa(addr, &ipbuf[1], sizeof ipbuf - 1); iplen = strlen(&ipbuf[1]); c = strlen(ipbuf); ipbuf[c] = '/'; c++; snprintf(&ipbuf[c], sizeof ipbuf - c, "%d", bits); exists = FALSE; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; /* try it with square brackets */ memmove(&ipbuf[2], &ipbuf[1], strlen(&ipbuf[1]) + 1); ipbuf[1] = '['; ipbuf[iplen + 2] = ']'; ipbuf[iplen + 3] = '/'; snprintf(&ipbuf[iplen + 4], sizeof ipbuf - iplen - 4, "%d", bits); exists = FALSE; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return FALSE; status = dkimf_db_get(db, &ipbuf[1], 0, NULL, 0, &exists); if (status != 0) return FALSE; if (exists) return TRUE; } } return FALSE; } #ifdef POPAUTH /* ** DKIMF_INITPOPAUTH -- initialize POPAUTH stuff ** ** Parameters: ** None. ** ** Return value: ** 0 on success, an error code on failure. See pthread_mutex_init(). */ int dkimf_initpopauth(void) { return pthread_mutex_init(&pop_lock, NULL); } /* ** DKIMF_CHECKPOPAUTH -- check a POP before SMTP database for client ** authentication ** ** Parameters: ** db -- DB handle to use for searching ** ip -- IP address to find ** ** Return value: ** TRUE iff the database could be opened and the client was verified. ** ** Notes: ** - does the key contain anything meaningful, like an expiry time? */ _Bool dkimf_checkpopauth(DKIMF_DB db, struct sockaddr *ip) { _Bool exists; int status; struct sockaddr_in *sin; struct in_addr addr; char ipbuf[DKIM_MAXHOSTNAMELEN + 1]; assert(ip != NULL); if (db == NULL) return FALSE; /* skip anything not IPv4 (for now) */ if (ip->sa_family != AF_INET) return FALSE; else sin = (struct sockaddr_in *) ip; memcpy(&addr.s_addr, &sin->sin_addr, sizeof addr.s_addr); dkimf_inet_ntoa(addr, ipbuf, sizeof ipbuf); exists = FALSE; status = dkimf_db_get(db, ipbuf, 0, NULL, 0, &exists); return (status == 0 && exists); } #endif /* POPAUTH */ #ifdef _FFR_REPLACE_RULES /* ** DKIMF_LOAD_REPLIST -- load a list of replace patterns ** ** Parameters: ** in -- input stream (must already be open) ** list -- list to be updated ** ** Return value: ** TRUE if successful, FALSE otherwise ** ** Side effects: ** Prints an error message when appropriate. */ _Bool dkimf_load_replist(FILE *in, struct replace **list) { int line; int status; char *p; struct replace *newrep; char rule[BUFRSZ + 1]; assert(in != NULL); assert(list != NULL); memset(rule, '\0', sizeof rule); while (fgets(rule, sizeof(rule) - 1, in) != NULL) { line++; for (p = rule; *p != '\0'; p++) { if (*p == '\n' || *p == '#') { *p = '\0'; break; } } if (dkimf_isblank(rule)) continue; newrep = (struct replace *) malloc(sizeof(struct replace)); if (newrep == NULL) { fprintf(stderr, "%s: malloc(): %s\n", progname, strerror(errno)); return FALSE; } p = strrchr(rule, '\t'); if (p == NULL) { free(newrep); return FALSE; } *p = '\0'; status = regcomp(&newrep->repl_re, rule, 0); if (status != 0) { fprintf(stderr, "%s: regcomp() failed\n", progname); free(newrep); return FALSE; } newrep->repl_txt = strdup(p + 1); if (newrep->repl_txt == NULL) { fprintf(stderr, "%s: strdup(): %s\n", progname, strerror(errno)); free(newrep); return FALSE; } newrep->repl_next = *list; *list = newrep; } return TRUE; } /* ** DKIMF_FREE_REPLIST -- destroy a list of replacement information ** ** Parameters: ** list -- list to destroy ** ** Return value: ** None. */ void dkimf_free_replist(struct replace *list) { struct replace *cur; struct replace *next; assert(list != NULL); for (cur = list; cur != NULL; cur = next) { next = cur->repl_next; regfree(&cur->repl_re); free(cur->repl_txt); free(cur); } } #endif /* _FFR_REPLACE_RULES */ /* ** DKIMF_INET_NTOA -- thread-safe inet_ntoa() ** ** Parameters: ** a -- (struct in_addr) to be converted ** buf -- destination buffer ** buflen -- number of bytes at buf ** ** Return value: ** Size of the resultant string. If the result is greater than buflen, ** then buf does not contain the complete result. */ size_t dkimf_inet_ntoa(struct in_addr a, char *buf, size_t buflen) { in_addr_t addr; assert(buf != NULL); addr = ntohl(a.s_addr); return snprintf(buf, buflen, "%d.%d.%d.%d", (addr >> 24), (addr >> 16) & 0xff, (addr >> 8) & 0xff, addr & 0xff); } /* ** DKIMF_TRIMSPACES -- trim trailing whitespace ** ** Parameters: ** str -- string to modify ** ** Return value: ** None. */ void dkimf_trimspaces(u_char *str) { size_t len = 0; u_char *p; u_char *last; u_char *firsttext = NULL; assert(str != NULL); last = NULL; for (p = str; *p != '\0'; p++) { len++; if (isascii(*p) && isspace(*p)) { if (last == NULL) { last = p; continue; } } else { last = NULL; if (firsttext == NULL) firsttext = p; } } if (last != NULL) *last = '\0'; if (firsttext != NULL && firsttext != str) memmove(str, firsttext, len - (firsttext - str) + 1); } /* ** DKIMF_STRIPCR -- remove CRs ** ** Parameters: ** str -- string to modify ** ** Return value: ** None. */ void dkimf_stripcr(char *str) { char *p; char *q; assert(str != NULL); for (p = str, q = str; *p != '\0'; p++) { if (*p == '\r') continue; if (q != p) *q = *p; q++; } if (q != p) *q = *p; } /* ** DKIMF_MKPATH -- generate a path ** ** Parameters: ** path -- output buffer ** pathlen -- bytes available at "path" ** root -- root to infer; if empty, use getcwd() ** file -- filename to use ** ** Return value: ** None. */ void dkimf_mkpath(char *path, size_t pathlen, char *root, char *file) { assert(path != NULL); assert(root != NULL); assert(file != NULL); if (file[0] == '/') /* explicit path */ { strlcpy(path, file, pathlen); } else if (root[0] == '\0') /* no root, use cwd */ { char *p; p = getcwd(path, pathlen); if (p == NULL) strlcpy(path, "./", pathlen); else strlcat(path, "/", pathlen); strlcat(path, file, pathlen); } else /* use root */ { strlcpy(path, root, pathlen); if (root[strlen(root) - 1] != '/') strlcat(path, "/", pathlen); strlcat(path, file, pathlen); } } /* ** DKIMF_HOSTLIST -- see if a hostname is in a pattern of hosts/domains ** ** Parameters: ** host -- hostname to compare ** list -- NULL-terminated char * array to search ** ** Return value: ** TRUE iff either "host" was in the list or it match a domain pattern ** found in the list. */ _Bool dkimf_hostlist(char *host, char **list) { int c; char *p; assert(host != NULL); assert(list != NULL); /* walk the entire list */ for (c = 0; list[c] != NULL; c++) { /* first try a full hostname match */ if (strcasecmp(host, list[c]) == 0) return TRUE; /* try each domain */ for (p = strchr(host, '.'); p != NULL; p = strchr(p + 1, '.')) { if (strcasecmp(p, list[c]) == 0) return TRUE; } } /* not found */ return FALSE; } /* ** DKIMF_DSTRING_RESIZE -- resize a dynamic string (dstring) ** ** Parameters: ** dstr -- DKIMF_DSTRING handle ** len -- number of bytes desired ** ** Return value: ** TRUE iff the resize worked (or wasn't needed) ** ** Notes: ** This will actually ensure that there are "len" bytes available. ** The caller must account for the NULL byte when requesting a ** specific size. */ static _Bool dkimf_dstring_resize(struct dkimf_dstring *dstr, int len) { int newsz; u_char *new; assert(dstr != NULL); assert(len > 0); if (dstr->ds_alloc >= len) return TRUE; /* must resize */ for (newsz = dstr->ds_alloc * 2; newsz < len; newsz *= 2) { /* impose ds_max limit, if specified */ if (dstr->ds_max > 0 && newsz > dstr->ds_max) { if (len <= dstr->ds_max) { newsz = len; break; } return FALSE; } /* check for overflow */ if (newsz > INT_MAX / 2) { /* next iteration will overflow "newsz" */ return FALSE; } } new = malloc(newsz); if (new == NULL) return FALSE; memcpy(new, dstr->ds_buf, dstr->ds_alloc); free(dstr->ds_buf); dstr->ds_alloc = newsz; dstr->ds_buf = new; return TRUE; } /* ** DKIMF_DSTRING_NEW -- make a new dstring ** ** Parameters: ** dkim -- DKIM handle ** len -- initial number of bytes ** maxlen -- maximum allowed length (0 == unbounded) ** ** Return value: ** A DKIMF_DSTRING handle, or NULL on failure. */ struct dkimf_dstring * dkimf_dstring_new(int len, int maxlen) { struct dkimf_dstring *new; /* fail on invalid parameters */ if ((maxlen > 0 && len > maxlen) || len == 0) return NULL; if (len < BUFRSZ) len = BUFRSZ; new = malloc(sizeof(struct dkimf_dstring)); if (new == NULL) return NULL; new->ds_buf = malloc(len); if (new->ds_buf == NULL) { free(new); return NULL; } memset(new->ds_buf, '\0', len); new->ds_alloc = len; new->ds_len = 0; new->ds_max = maxlen; return new; } /* ** DKIMF_DSTRING_FREE -- destroy an existing dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle to be destroyed ** ** Return value: ** None. */ void dkimf_dstring_free(struct dkimf_dstring *dstr) { assert(dstr != NULL); free(dstr->ds_buf); free(dstr); } /* ** DKIMF_DSTRING_COPY -- copy data into a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle to update ** str -- input string ** ** Return value: ** TRUE iff the copy succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkimf_dstring_copy(struct dkimf_dstring *dstr, u_char *str) { int len; assert(dstr != NULL); assert(str != NULL); len = strlen((char *) str); /* too big? */ if (dstr->ds_max > 0 && len >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= len) { /* nope; try to resize */ if (!dkimf_dstring_resize(dstr, len + 1)) return FALSE; } /* copy */ dstr->ds_len = strlcpy((char *) dstr->ds_buf, (char *) str, dstr->ds_alloc); return TRUE; } /* ** DKIMF_DSTRING_CAT -- append data onto a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle to update ** str -- input string ** ** Return value: ** TRUE iff the update succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkimf_dstring_cat(struct dkimf_dstring *dstr, u_char *str) { int len; assert(dstr != NULL); assert(str != NULL); len = strlen((char *) str) + dstr->ds_len; /* too big? */ if (dstr->ds_max > 0 && len >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= len) { /* nope; try to resize */ if (!dkimf_dstring_resize(dstr, len + 1)) return FALSE; } /* append */ dstr->ds_len = strlcat((char *) dstr->ds_buf, (char *) str, dstr->ds_alloc); return TRUE; } /* ** DKIMF_DSTRING_CAT1 -- append one byte onto a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle to update ** c -- input character ** ** Return value: ** TRUE iff the update succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkimf_dstring_cat1(struct dkimf_dstring *dstr, int c) { int len; assert(dstr != NULL); len = dstr->ds_len + 1; /* too big? */ if (dstr->ds_max > 0 && len >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= len) { /* nope; try to resize */ if (!dkimf_dstring_resize(dstr, len + 1)) return FALSE; } /* append */ dstr->ds_buf[dstr->ds_len++] = c; dstr->ds_buf[dstr->ds_len] = '\0'; return TRUE; } /* ** DKIMF_DSTRING_CATN -- append 'n' bytes onto a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle to update ** str -- input string ** nbytes -- number of bytes to append ** ** Return value: ** TRUE iff the update succeeded. ** ** Side effects: ** The dstring may be resized. */ _Bool dkimf_dstring_catn(struct dkimf_dstring *dstr, unsigned char *str, size_t nbytes) { size_t needed; assert(dstr != NULL); assert(str != NULL); needed = dstr->ds_len + nbytes; /* too big? */ if (dstr->ds_max > 0 && needed >= dstr->ds_max) return FALSE; /* fits now? */ if (dstr->ds_alloc <= needed) { /* nope; try to resize */ if (!dkimf_dstring_resize(dstr, needed + 1)) return FALSE; } /* append */ memcpy(dstr->ds_buf + dstr->ds_len, str, nbytes); dstr->ds_len += nbytes; dstr->ds_buf[dstr->ds_len] = '\0'; return TRUE; } /* ** DKIMF_DSTRING_GET -- retrieve data in a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle whose string should be retrieved ** ** Return value: ** Pointer to the NULL-terminated contents of "dstr". */ u_char * dkimf_dstring_get(struct dkimf_dstring *dstr) { assert(dstr != NULL); return dstr->ds_buf; } /* ** DKIMF_DSTRING_LEN -- retrieve length of data in a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle whose string should be retrieved ** ** Return value: ** Number of bytes in a dstring. */ int dkimf_dstring_len(struct dkimf_dstring *dstr) { assert(dstr != NULL); return dstr->ds_len; } /* ** DKIMF_DSTRING_BLANK -- clear out the contents of a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle whose string should be cleared ** ** Return value: ** None. */ void dkimf_dstring_blank(struct dkimf_dstring *dstr) { assert(dstr != NULL); dstr->ds_len = 0; dstr->ds_buf[0] = '\0'; } /* ** DKIMF_DSTRING_CHOP -- truncate contents of a dstring ** ** Parameters: ** dstr -- DKIMF_DSTRING handle whose string should be cleared ** len -- length after which to clobber ** ** Return value: ** None. */ void dkimf_dstring_chop(struct dkimf_dstring *dstr, int len) { assert(dstr != NULL); if (len < dstr->ds_len) { dstr->ds_len = len; dstr->ds_buf[len] = '\0'; } } /* ** DKIMF_DSTRING_PRINTF -- write variable length formatted output to a dstring ** ** Parameters: ** dstr -- DKIMF_STRING handle to be updated ** fmt -- format ** ... -- variable arguments ** ** Return value: ** New size, or -1 on error. */ size_t dkimf_dstring_printf(struct dkimf_dstring *dstr, char *fmt, ...) { size_t len; size_t rem; va_list ap; va_list ap2; assert(dstr != NULL); assert(fmt != NULL); va_start(ap, fmt); va_copy(ap2, ap); rem = dstr->ds_alloc - dstr->ds_len; len = vsnprintf((char *) dstr->ds_buf + dstr->ds_len, rem, fmt, ap); va_end(ap); if (len > rem) { if (!dkimf_dstring_resize(dstr, dstr->ds_len + len + 1)) { va_end(ap2); return (size_t) -1; } rem = dstr->ds_alloc - dstr->ds_len; len = vsnprintf((char *) dstr->ds_buf + dstr->ds_len, rem, fmt, ap2); } va_end(ap2); dstr->ds_len += len; return dstr->ds_len; } /* ** DKIMF_SOCKET_CLEANUP -- try to clean up the socket ** ** Parameters: ** sockspec -- socket specification ** ** Return value: ** 0 -- nothing to cleanup or cleanup successful ** other -- an error code (a la errno) */ int dkimf_socket_cleanup(char *sockspec) { int s; char *colon; struct sockaddr_un sock; assert(sockspec != NULL); /* we only care about "local" or "unix" sockets */ colon = strchr(sockspec, ':'); if (colon != NULL) { if (strncasecmp(sockspec, "local:", 6) != 0 && strncasecmp(sockspec, "unix:", 5) != 0) return 0; } /* find the filename */ if (colon == NULL) { colon = sockspec; } else { if (*(colon + 1) == '\0') return EINVAL; } /* get a socket */ s = socket(PF_UNIX, SOCK_STREAM, 0); if (s == -1) return errno; /* set up a connection */ memset(&sock, '\0', sizeof sock); #ifdef BSD sock.sun_len = sizeof sock; #endif /* BSD */ sock.sun_family = PF_UNIX; strlcpy(sock.sun_path, colon + 1, sizeof sock.sun_path); /* try to connect */ if (connect(s, (struct sockaddr *) &sock, (socklen_t) sizeof sock) != 0) { /* if ECONNREFUSED, try to unlink */ if (errno == ECONNREFUSED) { close(s); if (unlink(sock.sun_path) == 0) return 0; else return errno; } /* if ENOENT, the socket's not there */ else if (errno == ENOENT) { close(s); return 0; } /* something else happened */ else { int saveerr; saveerr = errno; close(s); return saveerr; } } /* connection apparently succeeded */ close(s); return EADDRINUSE; } /* ** DKIMF_MKREGEXP -- make a regexp string from a glob string ** ** Parameters: ** src -- source string ** dst -- destination string ** dstlen -- space available at "dest" ** ** Return value: ** TRUE iff "dest" was big enough (based on destlen) */ _Bool dkimf_mkregexp(char *src, char *dst, size_t dstlen) { char *p; char *q; char *end; assert(src != NULL); assert(dst != NULL); if (dstlen == 0) return FALSE; dst[0] = '^'; end = dst + dstlen; for (p = src, q = dst + 1; *p != '\0' && q < end; p++) { switch (*p) { case '*': *q = '.'; q++; *q = '*'; q++; break; case '+': *q = '\\'; q++; *q = '+'; q++; break; case '.': *q = '\\'; q++; *q = '.'; q++; break; default: *q = *p; q++; break; } } *q++ = '$'; if (q >= end) return FALSE; else return TRUE; } /* ** DKIMF_BASE64_ENCODE_FILE -- base64-encode a file ** ** Parameters: ** infd -- input file descriptor ** out -- output stream ** lm -- left margin ** rm -- right margin ** initial -- space consumed on the initial line ** ** Return value: ** None (yet). */ void dkimf_base64_encode_file(infd, out, lm, rm, initial) int infd; FILE *out; int lm; int rm; int initial; { int len; int bits; int c; int d; int char_count; ssize_t rlen; char buf[MAXBUFRSZ]; assert(infd >= 0); assert(out != NULL); assert(lm >= 0); assert(rm >= 0); assert(initial >= 0); bits = 0; char_count = 0; len = initial; (void) lseek(infd, 0, SEEK_SET); for (;;) { rlen = read(infd, buf, sizeof buf); if (rlen == -1) break; for (c = 0; c < rlen; c++) { bits += buf[c]; char_count++; if (char_count == 3) { fputc(alphabet[bits >> 18], out); fputc(alphabet[(bits >> 12) & 0x3f], out); fputc(alphabet[(bits >> 6) & 0x3f], out); fputc(alphabet[bits & 0x3f], out); len += 4; if (rm > 0 && lm > 0 && len >= rm - 4) { fputc('\n', out); for (d = 0; d < lm; d++) fputc(' ', out); len = lm; } bits = 0; char_count = 0; } else { bits <<= 8; } } if (rlen < (ssize_t) sizeof buf) break; } if (char_count != 0) { if (rm > 0 && lm > 0 && len >= rm - 4) { fputc('\n', out); for (d = 0; d < lm; d++) fputc(' ', out); } bits <<= 16 - (8 * char_count); fputc(alphabet[bits >> 18], out); fputc(alphabet[(bits >> 12) & 0x3f], out); if (char_count == 1) fputc('=', out); else fputc(alphabet[(bits >> 6) & 0x3f], out); fputc('=', out); } } /* ** DKIMF_SUBDOMAIN -- determine whether or not one domain is a subdomain ** of the other ** ** Parameters: ** d1 -- candidate domain ** d2 -- possible superdomain ** ** Return value: ** TRUE iff d1 is a subdomain of d2. */ _Bool dkimf_subdomain(char *d1, char *d2) { char *p; assert(d1 != NULL); assert(d2 != NULL); #if 0 if (strcasecmp(d1, d2) == 0) return TRUE; #endif /* 0 */ for (p = strchr(d1, '.'); p != NULL; p = strchr(p + 1, '.')) { if (strcasecmp(d2, p + 1) == 0) return TRUE; } return FALSE; } /* ** DKIMF_IPSTRING -- convert an IP address to a string ** ** Parameters: ** buf -- target buffer ** buflen -- bytes available at "buf" ** ss -- socket description ** ** Return value: ** None. */ void dkimf_ipstring(char *buf, size_t buflen, struct sockaddr_storage *ss) { assert(buf != NULL); assert(ss != NULL); switch (ss->ss_family) { case AF_INET: { struct sockaddr_in *sa; sa = (struct sockaddr_in *) ss; (void) inet_ntop(ss->ss_family, &sa->sin_addr, buf, buflen); break; } #ifdef AF_INET6 case AF_INET6: { struct sockaddr_in6 *sa; sa = (struct sockaddr_in6 *) ss; (void) inet_ntop(ss->ss_family, &sa->sin6_addr, buf, buflen); break; } #endif /* AF_INET6 */ default: break; } } #ifdef USE_UNBOUND /* ** DKIMF_TIMESPEC_PAST -- return TRUE iff the time described by a timespec ** structure has passed ** ** Parameters: ** ts -- timespec structure to evaluate ** ** Return value: ** TRUE if "tv" refers to a time in the past, false otherwise. */ _Bool dkimf_timespec_past(struct timespec *ts) { struct timeval now; assert(ts != NULL); (void) gettimeofday(&now, NULL); if (now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_usec * 1000 > ts->tv_nsec)) return TRUE; else return FALSE; } /* ** DKIMF_WAIT_FD -- wait for a descriptor to become read-ready ** ** Parameters: ** fd -- descriptor of interest ** until -- maximum wait time ** ** Return value: ** 1 -- descriptor is ready ** 0 -- timeout ** -1 -- error */ int dkimf_wait_fd(int fd, struct timespec *until) { fd_set fds; struct timeval now; struct timeval left; assert(fd >= 0); (void) gettimeofday(&now, NULL); if (until != NULL) { if (until->tv_sec < now.tv_sec || (until->tv_sec == now.tv_sec && until->tv_nsec < now.tv_usec * 1000)) { left.tv_sec = 0; left.tv_usec = 0; } else { left.tv_sec = until->tv_sec - now.tv_sec; left.tv_usec = until->tv_nsec / 1000 - now.tv_usec; if (until->tv_nsec / 1000 < now.tv_usec) { left.tv_usec += 1000000; left.tv_sec--; } } } FD_ZERO(&fds); FD_SET(fd, &fds); return select(fd + 1, &fds, NULL, NULL, until == NULL ? NULL : &left); } #endif /* USE_UNBOUND */ OpenDKIM-rel-opendkim-2-11-0-Beta2/opendkim/util.h000066400000000000000000000055321337314105200214160ustar00rootroot00000000000000/* ** Copyright (c) 2004, 2005, 2007-2009 Sendmail, Inc. and its suppliers. ** All rights reserved. ** ** Copyright (c) 2009, 2010, 2012, The Trusted Domain Project. ** All rights reserved. ** */ #ifndef _UTIL_H_ #define _UTIL_H_ /* system includes */ #include #include #include #include #include /* opendkim includes */ #include "build-config.h" #include "opendkim-db.h" /* TYPES */ struct dkimf_dstring; #ifdef _FFR_REPLACE_RULES /* ** REPLACE -- replacement table */ struct replace { regex_t repl_re; char * repl_txt; struct replace *repl_next; }; #endif /* _FFR_REPLACE_RULES */ /* PROTOTYPES */ extern void dkimf_base64_encode_file __P((int, FILE *, int, int, int)); extern _Bool dkimf_checkhost __P((DKIMF_DB, char *)); extern _Bool dkimf_checkip __P((DKIMF_DB, struct sockaddr *)); #ifdef POPAUTH extern _Bool dkimf_checkpopauth __P((DKIMF_DB, struct sockaddr *)); #endif /* POPAUTH */ extern _Bool dkimf_hostlist __P((char *, char **)); extern size_t dkimf_inet_ntoa __P((struct in_addr, char *, size_t)); #ifdef POPAUTH extern int dkimf_initpopauth __P((void)); #endif /* POPAUTH */ #ifdef _FFR_REPLACE_RULES extern void dkimf_free_replist __P((struct replace *)); extern _Bool dkimf_load_replist __P((FILE *, struct replace **)); #endif /* _FFR_REPLACE_RULES */ extern void dkimf_ipstring __P((char *, size_t, struct sockaddr_storage *)); extern _Bool dkimf_isblank __P((char *)); extern void dkimf_lowercase __P((u_char *)); extern void dkimf_mkpath __P((char *, size_t, char *, char *)); extern _Bool dkimf_mkregexp __P((char *, char *, size_t)); extern void dkimf_optlist __P((FILE *)); extern void dkimf_setmaxfd __P((void)); extern int dkimf_socket_cleanup __P((char *)); extern void dkimf_stripbrackets __P((char *)); extern void dkimf_stripcr __P((char *)); extern _Bool dkimf_subdomain __P((char *d1, char *d2)); extern void dkimf_trimspaces __P((u_char *)); extern struct dkimf_dstring *dkimf_dstring_new __P((int, int)); extern void dkimf_dstring_free __P((struct dkimf_dstring *)); extern _Bool dkimf_dstring_copy __P((struct dkimf_dstring *, u_char *)); extern _Bool dkimf_dstring_cat __P((struct dkimf_dstring *, u_char *)); extern _Bool dkimf_dstring_cat1 __P((struct dkimf_dstring *, int)); extern _Bool dkimf_dstring_catn __P((struct dkimf_dstring *, u_char *, size_t)); extern void dkimf_dstring_chop __P((struct dkimf_dstring *, int)); extern u_char *dkimf_dstring_get __P((struct dkimf_dstring *)); extern int dkimf_dstring_len __P((struct dkimf_dstring *)); extern void dkimf_dstring_blank __P((struct dkimf_dstring *)); extern size_t dkimf_dstring_printf __P((struct dkimf_dstring *, char *, ...)); #ifdef USE_UNBOUND extern _Bool dkimf_timespec_past __P((struct timespec *tv)); extern int dkimf_wait_fd __P((int fd, struct timespec *until)); #endif /* USE_UNBOUND */ #endif /* _UTIL_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/000077500000000000000000000000001337314105200177535ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/.gitignore000066400000000000000000000000561337314105200217440ustar00rootroot00000000000000opendkim-reprrdimport opendkim-reprrdimport.8 OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/Makefile.am000066400000000000000000000011261337314105200220070ustar00rootroot00000000000000# Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. AUTOMAKE_OPTIONS = foreign lib_LTLIBRARIES = libreprrd.la libreprrd_la_SOURCES = reprrd.c reprrd.h libreprrd_la_LIBADD = $(RRDTOOL_LIBS) libreprrd_la_LDFLAGS = -no-undefined $(PTHREAD_LDFLAGS) -version-info 1:0:0 libreprrd_la_CFLAGS = $(PTHREAD_CFLAGS) $(RRDTOOL_CFLAGS) libreprrd_la_CC = $(PTHREAD_CC) libreprrdincludedir = $(includedir)/reprrd libreprrdinclude_HEADERS = reprrd.h dist_doc_DATA = README reprrd.php reprrd-config.php dist_bin_SCRIPTS = opendkim-reprrdimport dist_man_MANS = opendkim-reprrdimport.8 OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/README000066400000000000000000000031451337314105200206360ustar00rootroot00000000000000This is the development area for the experimental DKIM-based reputation system that uses time series evaluation methods, as opposed to the contents of ../reputation which uses predictive inference. As with the other reputation system, this method uses the data collected by the statistics system as input. It also uses the concept of the NULL domain, defined in that system. Finally, it uses rrdtool[1] to maintain a sliding window of history about each source (messages and spam ratios). The tool applies time series forecasting to develop a notion of what is typical behaviour for the source over the course of a day (peaks and troughs) and then develops a range of values it considers to be expected. Deviations from that range are considered abnormal and can be dealt with. As of the time of this writing, the system produces the RRD tables for each domain whose mail has been signed (and soon for the NULL domain), and a PHP script is provided that can generate graphs on-demand for a given domain and data type, i.e., "messages" or "spam". The opendkim filter can make use of the RRD tables to determine if a domain is outside of its expected norms (overall traffic and spam ratio) and take corrective action when that conition is true. What remains is to test this in operation at scale, and to adjust the query to impose rate limits commensurate with spam predictions, as with the other reputation system. More complete documentation will be provided when the above work is complete. Users are welcome to experiment with what's been built so far and comment or improve on what's there. [1] http://oss.oetiker.ch/rrdtool/ OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/opendkim-reprrdimport.8.in000066400000000000000000000041071337314105200250100ustar00rootroot00000000000000.TH opendkim-reprrdimport 8 "The Trusted Domain Project" .SH NAME .B opendkim-reprrdimport \- OpenDKIM RRD statistics data import tool .SH SYNOPSIS .B opendkim-reprrdimport [options] .SH DESCRIPTION .B opendkim-reprrdimport collates data accumulated by the OpenDKIM statistics feature and stores them into RRD tables for forecasting analysis. See .B rrdtool(1) for information about RRD tables. .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --domain=name Only create/update RRD tables for the named domain. Can be specified multiple times, and .I name can also refer to a file from which domain names should be read. .TP .I --help Prints a usage message and exits. .TP .I --interval=n Retrieves records for the previous .I n days. The default is 1. A value of 0 retrieves data for all dates. .TP .I --levels=n Sets the depth of directory hashing levels to be used. The default is 2. .I n days. The default is 1. A value of 0 retrieves data for all dates. .TP .I --null Process the "null sender" as well (messages with no valid DKIM signature). .TP .I --rrdroot=path Defines the root directory for the RRD file hash tree. The default is .I /var/db/reprrd. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-reprrdimport that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/opendkim-reprrdimport.in000066400000000000000000000271231337314105200246450ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # # Script to import rate and spam counts from the stats tables into rrdtables. # EXPERIMENTAL. ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; use RRDs; require DBD::@SQL_BACKEND@; # general my $progname = basename($0); my $version = "@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my @domains; my $dbi_s; my $dbi_h; my $dbi_a; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $def_rrdroot = "/var/db/reprrd"; my $def_interval = 1; my $def_levels = 2; my $rrdroot; my $interval; my $levels; my $donull; my $dateclause; my $tmpin; my $idx; my $dbscheme = "@SQL_BACKEND@"; # Minimum messages.id value; used to mark the start of useful data my $minmsgid = 0; ### ### NO user-serviceable parts beyond this point ### sub rrd_path { my $name = shift; my $type = shift; my $path; my $c; if (!defined($name)) { die "$progname: rrd_path() called without a domain name\n"; } $path = $rrdroot . "/" . $type; if (! -d $path) { mkdir $path or die "$progname: cannot create directory $path: $!\n"; } for ($c = 0; $c < $levels; $c++) { $path = $path . "/" . substr($name, $c, 1); if (! -d $path) { mkdir $path or die "$progname: cannot create directory $path: $!\n"; } } $path = $path . "/" . $name; return $path; } sub make_rrd { my $name = shift; my $type = shift; my $timestamp = shift; my $path = $rrdroot; my $c; $path = rrd_path($name, $type); if (-e $path) { if (! -f $path) { die "$progname: $path is not a regular file\n"; } } else { if ($verbose) { print STDOUT "$progname: creating RRD table $path\n"; } $timestamp--; RRDs::create($path, "--start", "$timestamp", "--step", "3600", "DS:$type:GAUGE:3600:0:U", "RRA:AVERAGE:0.5:1:336", "RRA:HWPREDICT:336:0.1:0.0035:24") or die "$progname: failed to create RRD table $path: " . RRDs::error . "\n"; RRDs::tune($path, "--deltaneg", "100", "--failure-threshold", "1", "--window-length", "2") or die "$progname: failed to tune RRD table $path: " . RRDs::error . "\n"; } } sub update_rrd { my $domain; my $type; my $timestamp; my $value; my $path; my $data; my $cur; my $last; ($domain, $type, $timestamp, $value) = @_; $path = rrd_path($domain, $type); if ($verbose) { print STDOUT "$progname: updating RRD table $path for timestamp $timestamp\n"; } $last = RRDs::last($path) or die "$progname: failed to query RRD table $path: " . RRDs::error . "\n"; if ($last >= $timestamp) { if ($verbose > 0) { print STDOUT "$progname: skipping update to $path for timestamp $timestamp\n"; } return; } my ($start, $step, $columns, $values) = RRDs::fetch($path, "AVERAGE") or die "$progname: failed to fetch RRD table $path: " . RRDs::error . "\n"; for ($cur = $last + $step; $cur < $timestamp; $cur = $cur + $step) { $data = ${cur} . "\@0"; if ($verbose > 1) { print STDOUT "\t$data (FILL)\n"; } RRDs::update($path, $data) or die "$progname: failed to update RRD table $path: " . RRDs::error . "\n"; } $data = ${timestamp} . "@" . ${value}; if ($verbose > 1) { print STDOUT "\t$data\n"; } RRDs::update($path, $data) or die "$progname: failed to update RRD table $path: " . RRDs::error . "\n"; } sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--domains=list list of domains to process\n"; print STDERR "\t--interval=hour pull the previous n hours of data [$def_interval]\n"; print STDERR "\t--levels=n hashing depth [$def_levels]\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--null include the null sender\n"; print STDERR "\t--output=file output file\n"; print STDERR "\t--rrdroot=path root of RRD database tree [$def_rrdroot]\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # # parse command line arguments # my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'domain=s@' => \@domains, 'help!' => \$helponly, 'interval=i' => \$interval, 'levels=i' => \$levels, 'null!' => \$donull, 'rrdroot=s' => \$rrdroot, 'verbose+' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # # apply defaults # if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } if (defined($ENV{'OPENDKIM_MINMSGID'})) { $minmsgid = $ENV{'OPENDKIM_MINMSGID'}; } if (!defined($rrdroot)) { if (defined($ENV{'OPENDKIM_RRDROOT'})) { $rrdroot = $ENV{'OPENDKIM_RRDROOT'}; } else { $rrdroot = $def_rrdroot; } } if (!defined($levels)) { $levels = $def_levels; } if (!defined($interval)) { $interval = $def_interval; } # # If any of the domains started with "/" or "./", convert them into # whatever's in the files they reference. # if (scalar @domains > 0) { foreach $idx (0 .. $#domains) { if (substr($domains[$idx], 0, 1) eq "/" || substr($domains[$idx], 0, 2) eq "./") { if (!open($tmpin, "<", $domains[$idx])) { print STDERR "$progname: cannot open $domains[$idx]: $!\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while (<$tmpin>) { # ignore comments s/#.*//; # ignore blank lines next if /^(\s)*$/; chomp; push @domains, lc($_); } close($tmpin); delete $domains[$idx]; } else { $domains[$idx] = lc($domains[$idx]); } } } if ($verbose) { print STDERR "$progname: started at " . localtime() . "\n"; } # # open the SQL database # my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # Pull data per domain per hour within the interval (0 = epoch) # if ($verbose) { print STDERR "$progname: requesting hourly flow data\n"; } if ($interval == 0) { $dateclause = ""; } else { $dateclause = "AND msgtime >= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL $interval HOUR)"; } if ($donull) { $dbi_s = $dbi_h->prepare("SELECT UNIX_TIMESTAMP(TIMESTAMPADD(HOUR, HOUR(msgtime), DATE(msgtime))), COUNT(messages.id), SUM(SIGN(spam)) FROM messages WHERE (sigcount = 0 OR messages.id NOT IN (SELECT DISTINCT message FROM signatures WHERE pass = 1)) AND NOT spam = -1 AND msgtime < TIMESTAMPADD(HOUR, HOUR(CURRENT_TIMESTAMP()), DATE(CURRENT_TIMESTAMP())) $dateclause GROUP BY 1 ORDER BY 1"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { my $timestamp; my $count; my $spam; my $ratio; $timestamp = $dbi_a->[0]; $count = $dbi_a->[1]; $spam = $dbi_a->[2]; if (!defined($spam)) { next; } $ratio = $spam / $count; make_rrd("unsigned", "messages", $timestamp); update_rrd("unsigned", "messages", $timestamp, $count); make_rrd("unsigned", "spam", $timestamp); update_rrd("unsigned", "spam", $timestamp, $ratio); } $dbi_s->finish; } $dbi_s = $dbi_h->prepare("SELECT domains.name, UNIX_TIMESTAMP(TIMESTAMPADD(HOUR, HOUR(msgtime), DATE(msgtime))), COUNT(messages.id), SUM(SIGN(spam)) FROM messages JOIN signatures ON signatures.message = messages.id JOIN domains ON signatures.domain = domains.id WHERE NOT spam = -1 $dateclause AND msgtime < TIMESTAMPADD(HOUR, HOUR(CURRENT_TIMESTAMP()), DATE(CURRENT_TIMESTAMP())) GROUP BY 1, 2 ORDER BY 1, 2"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { my $domain; my $timestamp; my $count; my $spam; my $ratio; $domain = $dbi_a->[0]; $timestamp = $dbi_a->[1]; $count = $dbi_a->[2]; $spam = $dbi_a->[3]; if (!defined($spam)) { next; } if ($domain eq "(null)") { $domain = "null"; } $ratio = $spam / $count; $domain = lc($domain); if (@domains && grep({$_ eq $domain} @domains) == 0) { next; } make_rrd($domain, "messages", $timestamp); update_rrd($domain, "messages", $timestamp, $count); make_rrd($domain, "spam", $timestamp); update_rrd($domain, "spam", $timestamp, $ratio); } $dbi_s->finish; # # all done! # if ($verbose) { print STDERR "$progname: terminating at " . localtime() . "\n"; } $dbi_h->disconnect; exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/reprrd-config.php000066400000000000000000000004641337314105200232310ustar00rootroot00000000000000 OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/reprrd.c000066400000000000000000000206721337314105200214240ustar00rootroot00000000000000/* ** Copyright (c) 2012, 2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include /* librrd includes */ #include /* libreprrd includes */ #include "reprrd.h" /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* data types */ struct reprrd_handle { int rep_hashdepth; const char * rep_root; }; /* ** REPRRD_TYPE -- translate a type code to a string ** ** Parameters: ** code -- a REPRRD_TYPE_* constant ** ** Return value: ** Pointer to a static string representation of "code". */ static const char * reprrd_type(int code) { switch (code) { case REPRRD_TYPE_MESSAGES: return "messages"; case REPRRD_TYPE_SPAM: return "spam"; default: assert(0); } } /* ** REPRRD_INIT -- initialize a reputation RRD context ** ** Parameters: ** root -- root of the RRD directory tree ** hashdepth -- hashing depth in use ** ** Return value: ** A REPRRD object, used to launch future queries. */ REPRRD reprrd_init(const char *root, int hashdepth) { REPRRD new; assert(root != NULL); new = (REPRRD) malloc(sizeof(struct reprrd_handle)); if (new != NULL) { new->rep_hashdepth = hashdepth; new->rep_root = strdup(root); if (new->rep_root == NULL) { free(new); new = NULL; } } return new; } /* ** REPRRD_CLOSE -- destroy a reputation RRD context ** ** Parameters: ** r -- context to destroy ** ** Return value: ** None. */ void reprrd_close(REPRRD r) { assert(r != NULL); free((void *) r->rep_root); free(r); } /* ** REPRRD_MKPATH -- generate path to an RRD table ** ** Parameters: ** path -- path buffer ** pathlen -- size of path buffer ** r -- REPRRD context ** domain -- domain to query ** type -- table type ** ** Return value: ** A REPRRD_STAT_* constant. */ static REPRRD_STAT reprrd_mkpath(char *path, size_t pathlen, REPRRD r, const char *domain, int type) { int c; size_t len; assert(path != NULL); assert(pathlen > 0); assert(r != NULL); assert(domain != NULL); assert(type == REPRRD_TYPE_MESSAGES || type == REPRRD_TYPE_SPAM); snprintf(path, pathlen, "%s/%s", r->rep_root, reprrd_type(type)); for (c = 0; c < r->rep_hashdepth; c++) { len = strlcat(path, "/", pathlen); if (len >= pathlen) return REPRRD_STAT_INTERNAL; path[len] = domain[c]; path[len + 1] = '\0'; } (void) strlcat(path, "/", pathlen); len = strlcat(path, domain, pathlen); if (len >= pathlen) return REPRRD_STAT_INTERNAL; else return REPRRD_STAT_OK; } /* ** REPRRD_QUERY -- query a reputaton parameter for a domain ** ** Parameters: ** r -- REPRRD handle (query context) ** domain -- domain of interest ** type -- type of query (a REPRRD_TYPE_* constant) ** value -- current value (returned) ** err -- error buffer ** errlen -- bytes available at "err" ** ** Return value: ** A REPRRD_STAT_* constant. */ REPRRD_STAT reprrd_query(REPRRD r, const char *domain, int type, int *value, char *err, size_t errlen) { int c; int di; int status; time_t start; time_t end; unsigned long step; time_t ti; time_t now; u_long ds_cnt; char **ds_names; char **cdata; rrd_value_t *data; rrd_value_t d_flow; /* expected flow deviation */ rrd_value_t d_spam; /* expected spam deviation */ rrd_value_t a_flow; /* average flow */ rrd_value_t a_spam; /* average spam */ rrd_value_t p_flow; /* predicted flow */ rrd_value_t p_spam; /* predicted spam */ rrd_value_t r_flow; /* restricted flow */ rrd_value_t l_flow; /* last flow */ char path[MAXPATHLEN + 1]; assert(r != NULL); assert(domain != NULL); assert(value != NULL); assert(type == REPRRD_TYPE_MESSAGES || type == REPRRD_TYPE_SPAM || type == REPRRD_TYPE_LIMIT); (void) time(&now); if (type == REPRRD_TYPE_LIMIT) { time_t last_update; /* retrieve the most recent flow data */ reprrd_mkpath(path, sizeof path, r, domain, REPRRD_TYPE_MESSAGES); rrd_clear_error(); status = rrd_lastupdate_r(path, &last_update, &ds_cnt, &ds_names, &cdata); if (status != 0) { return (errno == ENOENT ? REPRRD_STAT_NODATA : REPRRD_STAT_QUERY); } di = 0; l_flow = NAN; for (c = 0; c < ds_cnt; c++) { if (cdata[di] == cdata[di]) l_flow = atof(cdata[di]); free(cdata[di++]); } for (c = 0; c < ds_cnt; c++) free(ds_names[c]); free(ds_names); free(cdata); if (l_flow != l_flow) return REPRRD_STAT_QUERY; /* ** Retrieve the predicted flow, which is the average plus ** twice the predicted deviation. */ end = now; start = last_update - 1; step = REPRRD_STEP; reprrd_mkpath(path, sizeof path, r, domain, REPRRD_TYPE_MESSAGES); rrd_clear_error(); status = rrd_fetch_r(path, REPRRD_CF_HWPREDICT, &start, &end, &step, &ds_cnt, &ds_names, &data); if (status != 0) { return (errno == ENOENT ? REPRRD_STAT_NODATA : REPRRD_STAT_QUERY); } di = 0; d_flow = NAN; for (ti = start + step; ti <= end; ti += step) { for (c = 0; c < ds_cnt; c++) { if (data[di] == data[di]) d_flow = data[di]; di++; } } for (c = 0; c < ds_cnt; c++) free(ds_names[c]); free(ds_names); free(data); if (d_flow != d_flow) return REPRRD_STAT_QUERY; end = now; start = last_update - 1; step = REPRRD_STEP; rrd_clear_error(); status = rrd_fetch_r(path, REPRRD_CF_AVERAGE, &start, &end, &step, &ds_cnt, &ds_names, &data); if (status != 0) { return (errno == ENOENT ? REPRRD_STAT_NODATA : REPRRD_STAT_QUERY); } di = 0; a_flow = NAN; for (ti = start + step; ti <= end; ti += step) { for (c = 0; c < ds_cnt; c++) { if (data[di] == data[di]) a_flow = data[di]; di++; } } for (c = 0; c < ds_cnt; c++) free(ds_names[c]); free(ds_names); free(data); if (a_flow != a_flow) return REPRRD_STAT_QUERY; p_flow = a_flow + d_flow * 2.; /* retrieve the predicted spam ratio */ end = now; start = last_update - 1; step = REPRRD_STEP; reprrd_mkpath(path, sizeof path, r, domain, REPRRD_TYPE_SPAM); rrd_clear_error(); status = rrd_fetch_r(path, REPRRD_CF_HWPREDICT, &start, &end, &step, &ds_cnt, &ds_names, &data); if (status != 0) { return (errno == ENOENT ? REPRRD_STAT_NODATA : REPRRD_STAT_QUERY); } di = 0; d_spam = NAN; for (ti = start + step; ti <= end; ti += step) { for (c = 0; c < ds_cnt; c++) { if (data[di] == data[di]) d_spam = data[di]; di++; } } for (c = 0; c < ds_cnt; c++) free(ds_names[c]); free(ds_names); free(data); if (d_spam != d_spam) return REPRRD_STAT_QUERY; end = now; start = last_update - 1; step = REPRRD_STEP; rrd_clear_error(); status = rrd_fetch_r(path, REPRRD_CF_AVERAGE, &start, &end, &step, &ds_cnt, &ds_names, &data); if (status != 0) { return (errno == ENOENT ? REPRRD_STAT_NODATA : REPRRD_STAT_QUERY); } di = 0; a_spam = NAN; for (ti = start + step; ti <= end; ti += step) { for (c = 0; c < ds_cnt; c++) { if (data[di] == data[di]) a_spam = data[di]; di++; } } for (c = 0; c < ds_cnt; c++) free(ds_names[c]); free(ds_names); free(data); if (a_spam != a_spam) return REPRRD_STAT_QUERY; /* prediction computation */ p_spam = a_spam + d_spam * 2.; /* apply the limiting algorithm */ r_flow = p_flow * (1. - p_spam); /* see if it's higher than expected */ *value = (l_flow >= r_flow); } else { reprrd_mkpath(path, sizeof path, r, domain, type); end = now; start = now - REPRRD_STEP * REPRRD_BACKSTEPS; step = REPRRD_STEP; rrd_clear_error(); status = rrd_fetch_r(path, REPRRD_CF_FAILURES, &start, &end, &step, &ds_cnt, &ds_names, &data); if (status != 0) { return (errno == ENOENT ? REPRRD_STAT_NODATA : REPRRD_STAT_QUERY); } di = 0; for (ti = start + step; ti <= end; ti += step) { for (c = 0; c < ds_cnt; c++) { if (data[di++] == (rrd_value_t) 1.0) *value = 1; } } for (c = 0; c < ds_cnt; c++) free(ds_names[c]); free(ds_names); free(data); } return REPRRD_STAT_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/reprrd.h000066400000000000000000000024101337314105200214170ustar00rootroot00000000000000/* ** Copyright (c) 2012, 2013, The Trusted Domain Project. All rights reserved. */ #ifndef _REPRRD_H_ #define _REPRRD_H_ /* system includes */ #include #include /* constants */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* status codes */ #define REPRRD_STAT_UNKNOWN (-1) /* unknown status */ #define REPRRD_STAT_OK 0 /* successful completion */ #define REPRRD_STAT_INTERNAL 1 /* internal error */ #define REPRRD_STAT_QUERY 2 /* query failure */ #define REPRRD_STAT_NODATA 3 /* no data for specified domain */ typedef int REPRRD_STAT; /* constants */ #define REPRRD_TYPE_UNKNOWN (-1) #define REPRRD_TYPE_MESSAGES 0 #define REPRRD_TYPE_SPAM 1 #define REPRRD_TYPE_LIMIT 2 #define REPRRD_BACKSTEPS 2 #define REPRRD_CF_AVERAGE "AVERAGE" #define REPRRD_CF_FAILURES "FAILURES" #define REPRRD_CF_HWPREDICT "HWPREDICT" #define REPRRD_DEFHASHDEPTH 2 #define REPRRD_STEP 3600 /* other types */ struct reprrd_handle; typedef struct reprrd_handle * REPRRD; /* prototypes */ extern void reprrd_close(REPRRD); extern REPRRD reprrd_init(const char *, int); extern REPRRD_STAT reprrd_query(REPRRD, const char *, int, int *, char *, size_t); #endif /* ! _REPRRD_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/reprrd.pc.in000066400000000000000000000007041337314105200222030ustar00rootroot00000000000000# Process this file with autoconf to produce a pkg-config metadata file. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: OpenDKIM RRD query library Description: Library for performing reputation queries for spammy domains using RRD tables URL: http://opendkim.org Version: @VERSION@ Libs: -L${libdir} @PTHREAD_CFLAGS@ -lreprrd Libs.private: @LIBRESOLV@ @PTHREAD_LIBS@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ OpenDKIM-rel-opendkim-2-11-0-Beta2/reprrd/reprrd.php000066400000000000000000000055441337314105200217720ustar00rootroot00000000000000 255) die("Malformed query (domain syntax)"); # # see if there's data available for the selected domain # $dompath = ""; for ($n = 0; $n < $rrddepth; $n++) { $dompath = $dompath . "/" . substr($domain, $n, 1); } $dompath = $dompath . "/" . $domain; $rrdpath = $rrdroot . "/" . $type . $dompath; if (!file_exists($rrdpath)) die("No " . $type . " data for " . $domain . " at " . $rrdpath); $test = fopen($rrdpath, "r"); if (!$test) die("Can't read from " . $rrdpath); fclose($test); # # generate graphs # $tmpdir = $rrdroot . "/tmp"; $tmppath = $tmpdir . "/" . $domain . "-" . $type . "-" . getmypid(); $test = fopen($tmppath, "w"); if (!$test) die("Can't write to " . $tmppath); fclose($test); $options = array ( "--imgformat=PNG", "--title=" . $domain . " " . $type . " at " . date("D, d M Y H:i:s"), "--start=-1209600", "--height=480", "--width=1500", "--alt-autoscale-max", "--lower-limit=0", "--vertical-label=Messages/Hour", "--slope-mode", "--font", "TITLE:8:", "--font", "AXIS:8:", "--font", "LEGEND:10:", "--font", "UNIT:8:", "DEF:a=" . $rrdpath . ":" . $type . ":AVERAGE", "DEF:b=" . $rrdpath . ":" . $type . ":HWPREDICT", "DEF:c=" . $rrdpath . ":" . $type . ":DEVPREDICT", "DEF:d=" . $rrdpath . ":" . $type . ":FAILURES", "CDEF:upper=b,c,2,*,+", "TICK:d#ccbb00:1.0:Failures", "LINE2:a#ff0000:Message Rate", "LINE1:upper#0000ff:Upper Bounds" ); printf("DEF:a=" . $rrdpath . ":messages:AVERAGE\n"); $out = rrd_graph($tmppath, $options); if (!$out) die("Failed to create graph at " . $tmppath); # # load graph for inline presentation # $in = fopen($tmppath, "r"); if (!$in) die("Can't open " . $tmppath); $imgraw = fread($in, filesize($tmppath)); fclose($in); $imgdata = base64_encode($imgraw); unlink($tmppath); # # output page # printf("Content-Type: text/html\n"); printf("\n"); printf("\n"); printf(" \n"); printf(" Recent " . $type . " history for " . $domain . "\n"); printf(" \n"); printf(" \n"); printf(" \""\n"); printf(" \n"); printf("\n"); # all done! ?> OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/000077500000000000000000000000001337314105200206475ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/.gitignore000066400000000000000000000001701337314105200226350ustar00rootroot00000000000000opendkim-genrates.8 opendkim-genrates opendkim-modtotals.8 opendkim-modtotals opendkim-rephistory.8 opendkim-rephistory OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/Makefile.am000066400000000000000000000017061337314105200227070ustar00rootroot00000000000000# Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. AUTOMAKE_OPTIONS = foreign dist_doc_DATA = README repute.php repute-config.php mkdb-rep.mysql lib_LTLIBRARIES = librepute.la librepute_la_SOURCES = repute.c repute.h librepute_la_LIBADD = $(PTHREAD_LIBS) $(LIBRESOLV) $(CURL_LIBS) $(LIBJANSSON_LIBS) ../libut/libut.la librepute_la_LDFLAGS = -no-undefined $(PTHREAD_CFLAGS) $(CURL_LDFLAGS) $(LIBJANSSON_LDFLAGS) -version-info 1:0:0 librepute_la_CFLAGS = $(PTHREAD_CFLAGS) $(CURL_CPPFLAGS) $(LIBJANSSON_CPPFLAGS) -I../libut librepute_la_CC = $(PTHREAD_CC) libreputeincludedir = $(includedir)/repute libreputeinclude_HEADERS = repute.h dist_sbin_SCRIPTS = opendkim-genrates opendkim-modtotals opendkim-rephistory if RPATH librepute_la_LDFLAGS += -rpath $(libdir) endif pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = repute.pc dist_man_MANS = opendkim-genrates.8 opendkim-modtotals.8 opendkim-rephistory.8 #dist_man_MANS = repute.3 OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/README000066400000000000000000000143001337314105200215250ustar00rootroot00000000000000INTRODUCTION This area contains a snapshot of the ongoing development of a rudimentary reputation system based on OpenDKIM's statistics package. The statistics package is able to capture the flow of mail arriving as it passes through OpenDKIM. All messages, even unsigned ones, are recorded. For signed messages, all signatures are recorded including pass/fail, signing domain, certain signature properties, etc. The statistics system can also upload the locally-collected data to an arbitrary central repository where it can be aggregated and then made available to participants to query. See the stats/README for details of this component. This central service implements a queryable system based on the REPUTE protocols under development within the Internet Engineering Task Force. This directory contains a description sufficient to build such a system, but also (and primarily) for building a local store that can be used as an intelligent filter based on DKIM verification results. REQUIREMENTS The requirements for this reputation system are as follows: 1) Reputation must be based on the domain(s) that have some kind of responsibility for the message. 2) Reputation should be expressed in such a way that it can be easily converted to a message flow limit. 3) There must be some reasonable, even if tiny, allowance made for domains about which no data have been accumulated. 4) The system may output a few values for a given domain, such as "strict", "medium" and "light", and these would be applied at the discretion of the implementation. 5) Data expiration must be configurable at the discretion of the site using the system. That is, the system should neither impose a specific lifetime of the data accumulated, though it should discuss the impacts of different choices of data lifetime. OVERVIEW The system computes a recommended flow based on the history of the behaviour of the signing domain(s) on a message. Mail that is unsigned will be treated as though it was signed by the NULL domain, meaning all unsigned mail is presumed to come from a common source ("the unknown", as it were). What remains, then, is to determine the perceived value of mail from each of these sources. This is done via data collection and statistical methods. Full details of this system can be found in the white paper entitled "Enforcing Rate Limits Based on Authenticated Sender Reputation", which will be included in this directory upon publication. SETUP INSTRUCTIONS 1) If you intend only to query for reputations, skip to step 11. 2) Follow the steps to get opendkim configured for creating statistics reports. In addition, install contrib/stats/stats.lua someplace and reference it in a StatisticsPolicyScript line in your configuration file. Note that only the "SpamAssassin" portion is required. 3) If you intend to submit your data, follow the steps to create and register a submission key (GPG required), and then begin sending your reports regularly via cron(8). Skip to step 11. 4) If you intend to do local reputation, create a new SQL database with tables as described in stats/mkdb.mysql and in reputation/mkdb-rep.mysql. (You may need to edit these if you are using a backend other than MySQL.) 5) Rather than (or in addition to) sending your stats reports off to a central site, import them periodically to your own database using cron(8) and opendkim-importstats(8). 6) Somewhere soon after midnight daily, arrange to run opendkim-genrates(8). This takes your statistical reports from SQL and rolls them up into spam and flow predictions, which opendkim can then query. 7) Install a web server (e.g., Apache), and ensure it includes support for inline PHP. 8) Select a URI that will be the root of your reputation query. Configure your web server such that this URI points to a specific directory. This documentation refers to that directory as $REPROOT. 9) Create a REPUTE query template that will be returned from http:///.well-known/repute-template. This would be in $REPROOT/.well-known/repute-template. The template describes to a REPUTE client how to form the HTTP query that your server will use. The template used for this experimental work is as follows: http://{service}/repute.php{?subject,application,assertion,service,reporter} 10) Install reputation/repute.php and reputation/repute-config.php into $REPROOT. Edit repute-config.php as needed to match your database parameters. 11) Configure opendkim to query the reputation server by adding these configuration items: ReputationRatios repute: ReputationLimits repute:: ReputationTimeFactor 24 ReputationMinimum 2 ReputationSpamCheck /^X-Spam: ?[Yy][Ee][Ss]/ This tells opendkim the following things: - domain reputations should be obtained via the REPUTE protocol from - message limits based on those reputations should also be retrieved from the same service; you may include your own if you have one to get limits tailored to your site based on the data you have reported - the daily limit should be enforced in 24 chunks (i.e., applied hourly rather than daily) - any domain is allowed to get at least two messages in regardless of its reputation or the "spam" verdict on a message - a message is spam if any header field matches the regular expression shown If you have configured a local reputation service, you can replace the ReputationLimits and ReputationRatios setting with a query to the data set that contains those numbers for you, i.e., the "daily_limit_low" and "rate_high" columns in the "predictions" table. TROUBLESHOOTING [some troubleshooting tips will be added here as experience is gained] SUPPORT/QUESTIONS/COMMENTS This work is still evolving. For support, subscribe to the "opendkim-users" list at http://lists.opendkim.org and post your question there. To report bugs or assist in development, subscribe to the "opendkim-dev" list at http://lists.opendkim.org and post there. Please do not use the trackers at SourceForge for reporting bugs or filing feature requests until this work is no longer considered experimental. OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/mkdb-rep.mysql000066400000000000000000000034431337314105200234430ustar00rootroot00000000000000-- Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. -- MySQL command sequence to create a database to accumulate OpenDKIM -- reputation data -- table containing data aggregation for staging to predictions create table if not exists aggregate ( id int auto_increment, reporter int, domain int not null, updated timestamp not null default current_timestamp on update current_timestamp, date timestamp not null default '0000-00-00 00:00:00', messages int, spam int, ratio float, primary key (id), unique key (domain, date, reporter) ) engine=innodb default charset=latin1; -- table mapping domain codes to flow predictions create table if not exists predictions ( id int not null auto_increment, reporter int, domain int not null, name varchar(255), updated timestamp not null default current_timestamp on update current_timestamp, rate_samples int, rate_max int, rate_avg float, rate_stddev float, rate_high int, ratio_max float, ratio_avg float, ratio_stddev float, ratio_high float, daily_limit_high int, daily_limit_low int, today_mail int, today_spam float, primary key (id), key (name), unique key (domain, reporter) ) engine=innodb default charset=latin1; -- table containing reputation history create table if not exists history ( id int not null auto_increment, date timestamp not null, domain int not null, maxmsgs int, maxspam float, maxlimit int, primary key(id), unique key(domain, date) ) engine=innodb default charset=latin1; -- alter domains table to contain "low time" flag alter table domains add column low_time tinyint unsigned not null default 0; -- For upgrading from pre-2.8.0 releases: -- -- alter table history add column maxmsgs int after domain, change -- column ratio maxspam float, change column msglimit maxlimit int; OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/opendkim-genrates.8.in000066400000000000000000000044301337314105200247620ustar00rootroot00000000000000.TH opendkim-genrates 8 "The Trusted Domain Project" .SH NAME .B opendkim-genrates \- OpenDKIM recommended rate computation tool .SH SYNOPSIS .B opendkim-genrates [options] .SH DESCRIPTION .B opendkim-genrates collates data accumulated by the OpenDKIM statistics feature into daily summaries that are then used to compute a recommended rate limit for each signing domain. It also generates a report of its findings, which includes some specific (currently hard-coded) interesting domains. The schemae that are used both as input (tables from which the values are taken) and output (tables into which results are stored) can be found in the .I stats/mkdb.mysql file in the OpenDKIM package. The target tables are called "aggregate" and "predictions". This latter table can then be used by mail filtering software to impose flow and spam ratio limits on a per-domain basis. For a detailed description of the algorithms, see the white paper "Enforcing Rate Limits Based on Authenticated Sender Reputation." This work is experimental. .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --help Prints a usage message and exits. .TP .I --output=file Writes an HTML report to the specified .I file. .TP .I --prediction=pct For calculations, constructs a prediction interval described by the percentage value .I pct. The default is 75. Accepted values are 50, 68, 75, 90, 95 and 99. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-genrates that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/opendkim-genrates.in000066400000000000000000000513231337314105200246170ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # # # Script to generate rate and spam ratio predictions for each domain # based on accumulated data. EXPERIMENTAL. ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::@SQL_BACKEND@; # general my $progname = basename($0); my $version = "@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my @domains; my $out; my $idx; my $id; my $tmpsql; my $tmpin; my $dbi_s; my $dbi_h; my $dbi_a; my $thresh; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "@SQL_BACKEND@"; # output location (default) my $reportout; my $tmpout; # "spammy" ratio default my $spamratio = 0.75; # minimum message count for consideration my $minmsgs = 10; my $minspamcount = 2; # prediction interval calculation my $def_pi = 75; my $pisize; my $stdscore; my %stdscores = ( 50, 0.67, 68, 1.00, 75, 1.15, 90, 1.64, 95, 1.96, 99, 2.58 ); # Minimum messages.id value; used to mark the start of useful data my $minmsgid = 0; ### ### NO user-serviceable parts beyond this point ### sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--domains=list list of domains to include in report\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--output=file output file\n"; print STDERR "\t--prediction=pct prediction interval [$def_pi]\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'domain=s@' => \@domains, 'help!' => \$helponly, 'output=s' => \$reportout, 'prediction=i' => \$pisize, 'verbose!' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # apply defaults if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } if (!defined($reportout)) { if (defined($ENV{'OPENDKIM_OUTPUT'})) { $reportout = $ENV{'OPENDKIM_OUTPUT'}; } } if (defined($ENV{'OPENDKIM_MINMSGID'})) { $minmsgid = $ENV{'OPENDKIM_MINMSGID'}; } # # If any of the domains started with "/" or "./", convert them into # whatever's in the files they reference. # if (scalar @domains > 0) { foreach $idx (0 .. $#domains) { if (substr($domains[$idx], 0, 1) eq "/" || substr($domains[$idx], 0, 2) eq "./") { if (!open($tmpin, "<", $domains[$idx])) { print STDERR "$progname: cannot open $domains[$idx]: $!\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while (<$tmpin>) { # ignore comments s/#.*//; # ignore blank lines next if /^(\s)*$/; chomp; push @domains, $_; } close($tmpin); delete $domains[$idx]; } } } if ($verbose) { print STDERR "$progname: started at " . localtime() . "\n"; } if (!defined($pisize)) { $pisize = $def_pi; } $stdscore = $stdscores{$pisize}; if (!defined($stdscore)) { print STDERR "$progname: unknown prediction interval size $pisize\n"; exit(1); } elsif ($verbose) { print STDERR "$progname: using standard score $stdscore\n"; } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # Convert domain names to domain IDs # if (scalar @domains > 0) { $tmpsql = "SELECT id FROM domains WHERE name IN ("; $id = 0; foreach $idx (0 .. $#domains) { if (!defined($domains[$idx])) { next; } if ($id != 0) { $tmpsql = $tmpsql . ", "; } $tmpsql = $tmpsql . "'" . $domains[$idx] . "'"; $id++; } $tmpsql = $tmpsql . ")"; $dbi_s = $dbi_h->prepare($tmpsql); if (!$dbi_s->execute) { print STDERR "$progname: failed to collect domain IDs: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $tmpin = $dbi_s->fetchall_arrayref([0]); } # # start the report # if (defined($reportout)) { $tmpout = $reportout . "." . $$; open($out, ">", $tmpout) or die "$progname: can't open $tmpout: $!"; if ($verbose) { print STDERR "$progname: report started in $tmpout\n"; } print $out "\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " OpenDKIM Rate Recommendations\n"; print $out " \n"; print $out " \n"; print $out "\n"; print $out " \n"; print $out "

OpenDKIM Rate Recommendations

\n"; print $out "Generated " . strftime("%b %e %Y %H:%M:%S", localtime) . "\n"; print $out "
\n"; } # # compute the low-time threshold # if ($verbose) { print STDERR "$progname: computing low-time threshold\n"; } if (defined($reportout)) { print $out "Analysis of high spam domain duration (>= " . $spamratio * 100 . "% spam, >= " . $minspamcount . " msg(s))\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } $dbi_s = $dbi_h->prepare("SELECT COUNT(c) AS domains, MIN(l) AS 'min duration', MAX(l) AS 'max duration', AVG(l) AS 'mean duration', STDDEV_POP(l) AS 'duration stddev' FROM (SELECT COUNT(messages.id) AS c, SUM(messages.spam)/COUNT(messages.id) AS r, DATEDIFF(MAX(messages.msgtime), MIN(messages.msgtime)) AS l FROM signatures JOIN messages ON signatures.message = messages.id WHERE messages.id >= $minmsgid AND NOT spam = -1 AND pass = 1 GROUP BY signatures.domain) t1 WHERE r >= $spamratio AND c >= $minspamcount"); if (!$dbi_s->execute) { print STDERR "$progname: report #1 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } else { while ($dbi_a = $dbi_s->fetchrow_arrayref()) { if (defined($reportout)) { print $out " \n"; for ($idx = 0; $idx < 5; $idx++) { if (defined($dbi_a->[$idx])) { print $out " \n"; } else { print $out " \n"; } } print $out " \n"; } if (defined($dbi_a->[3]) && defined($dbi_a->[4])) { $thresh = $dbi_a->[3] + $dbi_a->[4] * $stdscore; } } } $dbi_s->finish; if (defined($reportout)) { print $out "
DomainsMin. DurationMax. DurationMean DurationDuration Std. Dev.
" . $dbi_a->[$idx] . " NULL
\n"; print $out "
\n"; } if (!defined($thresh)) { print STDERR "$progname: unable to determine low-time threshold\n"; $dbi_h->disconnect; exit(1); } if ($verbose) { print STDERR "$progname: low time threshold is $thresh day(s)\n"; } # # Tag domains that are low-time # if ($verbose) { print STDERR "$progname: updating low_time flag\n"; } $dbi_s = $dbi_h->prepare("UPDATE domains SET low_time = IF(DATEDIFF(DATE(NOW()), DATE(firstseen)) < $thresh, 1, 0)"); if (!$dbi_s->execute) { print STDERR "$progname: low_time update failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute/update overall message counts and spam ratios for all signing domains # if ($verbose) { print STDERR "$progname: computing overall counts and ratios for signers\n"; } $dbi_s = $dbi_h->prepare("INSERT IGNORE INTO aggregate (domain, updated, date, messages, spam, reporter) SELECT signatures.domain, CURRENT_TIMESTAMP(), DATE(messages.msgtime), COUNT(messages.id), SUM(spam), 0 FROM messages JOIN signatures ON signatures.message = messages.id WHERE NOT spam = -1 AND pass = 1 AND messages.id >= $minmsgid AND NOT DATE(messages.msgtime) = DATE(CURRENT_TIMESTAMP()) GROUP BY 1, 3"); if (!$dbi_s->execute) { print STDERR "$progname: pass #1 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute/update per-reporter message counts and spam ratios for all # signing domains # if ($verbose) { print STDERR "$progname: computing per-reporter counts and ratios for signers\n"; } $dbi_s = $dbi_h->prepare("INSERT IGNORE INTO aggregate (domain, updated, date, messages, spam, reporter) SELECT signatures.domain, CURRENT_TIMESTAMP(), DATE(messages.msgtime), COUNT(messages.id), SUM(spam), reporter FROM messages JOIN signatures ON signatures.message = messages.id WHERE NOT spam = -1 AND pass = 1 AND messages.id >= $minmsgid AND NOT DATE(messages.msgtime) = DATE(CURRENT_TIMESTAMP()) GROUP BY 1, 3, 6"); if (!$dbi_s->execute) { print STDERR "$progname: pass #2 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute/update overall message counts and spam ratios for unsigned mail # if ($verbose) { print STDERR "$progname: computing overall counts and ratios for unsigned mail\n"; } $dbi_s = $dbi_h->prepare("INSERT IGNORE INTO aggregate (domain, updated, date, messages, spam, reporter) SELECT 0, CURRENT_TIMESTAMP(), DATE(messages.msgtime), COUNT(messages.id), SUM(spam), 0 FROM messages WHERE NOT spam = -1 AND messages.id >= $minmsgid AND NOT DATE (messages.msgtime) = DATE(CURRENT_TIMESTAMP()) AND (sigcount = 0 OR messages.id NOT IN (SELECT message FROM signatures WHERE pass = 1)) GROUP BY 3"); if (!$dbi_s->execute) { print STDERR "$progname: pass #3 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute/update per-reporter message counts and spam ratios for unsigned mail # if ($verbose) { print STDERR "$progname: computing per-reporter counts and ratios for unsigned mail\n"; } $dbi_s = $dbi_h->prepare("INSERT IGNORE INTO aggregate (domain, updated, date, messages, spam, reporter) SELECT 0, CURRENT_TIMESTAMP(), DATE(messages.msgtime), COUNT(messages.id), SUM(spam), reporter FROM messages WHERE NOT spam = -1 AND messages.id >= $minmsgid AND NOT DATE (messages.msgtime) = DATE(CURRENT_TIMESTAMP()) AND (sigcount = 0 OR messages.id NOT IN (SELECT message FROM signatures WHERE pass = 1)) GROUP BY 3, 6"); if (!$dbi_s->execute) { print STDERR "$progname: pass #4 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute overall counts and ratios for low-time domains # if ($verbose) { print STDERR "$progname: computing overall counts and ratios for low-time domains\n"; } $dbi_s = $dbi_h->prepare("INSERT IGNORE INTO aggregate (domain, updated, date, messages, spam, reporter) SELECT -1, CURRENT_TIMESTAMP(), DATE(messages.msgtime), COUNT(messages.id), SUM(spam), 0 FROM messages JOIN signatures ON signatures.message = messages.id JOIN domains on signatures.domain = domains.id WHERE NOT spam = -1 AND messages.id >= $minmsgid AND NOT DATE (messages.msgtime) = DATE(CURRENT_TIMESTAMP()) AND (sigcount = 0 OR messages.id NOT IN (SELECT message FROM signatures WHERE pass = 1)) AND DATEDIFF(DATE(NOW()), DATE(domains.firstseen)) < $thresh GROUP BY 3"); if (!$dbi_s->execute) { print STDERR "$progname: pass #5 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute per-reporter counts and ratios for low-time domains # if ($verbose) { print STDERR "$progname: computing per-reporter counts and ratios for low-time domains\n"; } $dbi_s = $dbi_h->prepare("INSERT IGNORE INTO aggregate (domain, updated, date, messages, spam, reporter) SELECT -1, CURRENT_TIMESTAMP(), DATE(messages.msgtime), COUNT(messages.id), SUM(spam), reporter FROM messages JOIN signatures ON signatures.message = messages.id JOIN domains on signatures.domain = domains.id WHERE NOT spam = -1 AND messages.id >= $minmsgid AND NOT DATE (messages.msgtime) = DATE(CURRENT_TIMESTAMP()) AND (sigcount = 0 OR messages.id NOT IN (SELECT message FROM signatures WHERE pass = 1)) AND DATEDIFF(DATE(NOW()), DATE(domains.firstseen)) < $thresh GROUP BY 3, 6"); if (!$dbi_s->execute) { print STDERR "$progname: pass #6 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute ratios wherever they're missing # if ($verbose) { print STDERR "$progname: computing missing ratios\n"; } $dbi_s = $dbi_h->prepare("UPDATE aggregate SET ratio = spam / messages WHERE ratio IS NULL"); if (!$dbi_s->execute) { print STDERR "$progname: pass #7 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Compute predictions # if ($verbose) { print STDERR "$progname: computing specific domain predictions\n"; } $dbi_s = $dbi_h->prepare("INSERT INTO predictions (reporter, domain, name, rate_samples, rate_max, rate_avg, rate_stddev, rate_high, ratio_max, ratio_avg, ratio_stddev, ratio_high, daily_limit_low, daily_limit_high) SELECT reporter, domain, domains.name, COUNT(aggregate.messages), MAX(aggregate.messages), AVG(aggregate.messages), STDDEV_POP(aggregate.messages), AVG(aggregate.messages) + STDDEV_POP(aggregate.messages) * $stdscore, MAX(aggregate.ratio), AVG(aggregate.ratio), STDDEV_POP(aggregate.ratio), AVG(aggregate.ratio) + STDDEV_POP(aggregate.ratio) * $stdscore, (AVG(aggregate.messages) + STDDEV_POP(aggregate.messages) * $stdscore) * (1 - (AVG(aggregate.ratio) + STDDEV_POP(aggregate.ratio) * $stdscore)), (AVG(aggregate.messages) + STDDEV_POP(aggregate.messages) * $stdscore) * (1 - (AVG(aggregate.ratio) - STDDEV_POP(aggregate.ratio) * $stdscore)) FROM aggregate LEFT JOIN domains ON aggregate.domain = domains.id GROUP BY 1, 2 ON DUPLICATE KEY UPDATE updated = NOW(), name = VALUES(name), rate_samples = VALUES(rate_samples), rate_max = VALUES(rate_max), rate_avg = VALUES(rate_avg), rate_stddev = VALUES(rate_stddev), rate_high = VALUES(rate_high), ratio_max = VALUES(ratio_max), ratio_avg = VALUES(ratio_avg), ratio_stddev = VALUES(ratio_stddev), ratio_high = VALUES(ratio_high), daily_limit_low = VALUES(daily_limit_low), daily_limit_high = VALUES(daily_limit_high)"); if (!$dbi_s->execute) { print STDERR "$progname: pass #8 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # Add query labels # if ($verbose) { print STDERR "$progname: adding queryable names to special domains\n"; } $dbi_s = $dbi_h->prepare("UPDATE predictions SET name = 'UNSIGNED' WHERE domain = 0"); if (!$dbi_s->execute) { print STDERR "$progname: pass #9 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; $dbi_s = $dbi_h->prepare("UPDATE predictions SET name = 'LOW-TIME' WHERE domain = -1"); if (!$dbi_s->execute) { print STDERR "$progname: pass #10 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; # # reports # if (defined($reportout)) { if ($verbose) { print STDERR "$progname: reporting on interesting domains\n"; } print $out "$pisize% prediction interval, standard score $stdscore\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $tmpsql = "SELECT domain, name, reporter, rate_avg, rate_max, rate_stddev, rate_high, ratio_avg, ratio_max, ratio_stddev, ratio_high, daily_limit_low, daily_limit_high FROM predictions WHERE domain IN (0, -1"; foreach (@$tmpin) { $id = $_->[0]; if (!defined($id)) { next; } $tmpsql = $tmpsql . ", ". $id; } $tmpsql = $tmpsql . ")"; $dbi_s = $dbi_h->prepare($tmpsql); if (!$dbi_s->execute) { print STDERR "$progname: domain ID collection failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } else { while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; for ($idx = 0; $idx < 13; $idx++) { if (defined($dbi_a->[$idx])) { print $out " \n"; } else { print $out " \n"; } } print $out " \n"; } } print $out "
Domain IDDomain NameReporter IDMean RateMax RateRate Std. Dev.Rate High PredictionMean Spam RatioMax Spam RatioSpam Ratio Std. Dev.Spam Ratio High PredictionVolume Limit (low)Volume Limit (high)
" . $dbi_a->[$idx] . " NULL
\n"; print $out "
\n"; $dbi_s->finish; # # low-time behaviour analysis # if ($verbose) { print STDERR "$progname: reporting on low-time domain behaviour\n"; } print $out "Analysis of low-time domain behaviour (<= " . $thresh . " days, >= " . $minmsgs . " msg(s))\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(c) AS domains, MAX(counts.c) AS rate_max, AVG(counts.c) AS rate_avg, STDDEV_POP(counts.c) AS rate_stddev, AVG(counts.c) + STDDEV_POP(counts.c) * $stdscore AS rate_high, MAX(counts.r) AS ratio_max, AVG(counts.r) AS ratio_avg, STDDEV_POP(counts.r) AS ratio_stddev, AVG(counts.r) - STDDEV_POP(counts.r) * $stdscore AS ratio_low, AVG(counts.r) + STDDEV_POP(counts.r) * $stdscore AS ratio_high, AVG(counts.c) + STDDEV_POP(counts.c) * $stdscore * (1 - (AVG(counts.r) + STDDEV_POP(counts.r) * $stdscore)) AS daily_limit FROM (SELECT SUM(messages) AS c, SUM(spam)/SUM(messages) AS r FROM aggregate JOIN domains ON aggregate.domain = domains.id WHERE domains.firstseen >= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL $thresh DAY) GROUP BY domain HAVING SUM(messages) >= $minmsgs) counts"); if (!$dbi_s->execute) { print STDERR "$progname: report #2 failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } else { while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; for ($idx = 0; $idx < 11; $idx++) { if (defined($dbi_a->[$idx])) { print $out " \n"; } else { print $out " \n"; } } print $out " \n"; } } print $out "
DomainsMax RateMean RateRate Std. Dev.Rate High PredictionMax Spam RatioMean Spam RatioSpam Ratio Std. Dev.Spam Ratio Low PredictionSpam Ratio High PredictionVolume Limit
" . $dbi_a->[$idx] . " NULL
\n"; $dbi_s->finish; # footer print $out " \n"; print $out "\n"; } # all done! if ($verbose) { print STDERR "$progname: terminating at " . localtime() . "\n"; } $dbi_h->disconnect; if (defined($reportout)) { close $out; rename($tmpout, $reportout) or die "$progname: rename to $reportout failed; $!"; } exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/opendkim-modtotals.8.in000066400000000000000000000033231337314105200251600ustar00rootroot00000000000000.TH opendkim-modtotals 8 "The Trusted Domain Project" .SH NAME .B opendkim-modtotals \- OpenDKIM statistics update tool .SH SYNOPSIS .B opendkim-modtotals.pl [options] .SH DESCRIPTION .B opendkim-modtotals collates data accumulated by the OpenDKIM statistics feature about today's flow of mail, updating stored values about data observed so far in the current day. The OpenDKIM filter can then use this information and the output of the .I opendkim-genrates script to apply reputation-based filtering of signing domains. For a detailed description of the algorithms, see the white paper "Enforcing Rate Limits Based on Authenticated Sender Reputation." This work is experimental. .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --help Prints a usage message and exits. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-modtotals that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-genrates(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/opendkim-modtotals.in000066400000000000000000000110341337314105200250100ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # # # Script to update current daily message and spam counts for each domain. # EXPERIMENTAL. ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::@SQL_BACKEND@; # general my $progname = basename($0); my $version = "\@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my $out; my $idx; my $dbi_h; my $dbi_counts; my $dbi_update; my $dbi_a; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "@SQL_BACKEND@"; ### ### NO user-serviceable parts beyond this point ### sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'help!' => \$helponly, 'verbose!' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # apply defaults if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # Compute/update message counts and spam ratios for all signing domains # if ($verbose) { print STDERR "$progname: updating counts and ratios for signers\n"; } $dbi_counts = $dbi_h->prepare("SELECT signatures.domain, COUNT(messages.id), SUM(spam) FROM signatures JOIN messages ON signatures.message = messages.id WHERE NOT spam = -1 AND DATE(msgtime) = DATE(NOW()) GROUP BY signatures.domain"); $dbi_update = $dbi_h->prepare("UPDATE predictions SET today_mail = ?, today_spam = ? WHERE domain = ?"); if (!$dbi_counts->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_counts->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_counts->fetchrow_arrayref()) { my $domain = $dbi_a->[0]; my $count = $dbi_a->[1]; my $ratio = $dbi_a->[2] / $dbi_a->[1]; if ($verbose) { print STDERR "$progname: domain $domain count $count ratio $ratio\n"; } if (!$dbi_update->execute("$count", "$ratio", "$domain")) { print STDERR "$progname: UPDATE failed: " . $dbi_h->errstr; $dbi_counts->finish; $dbi_h->disconnect; exit(1); } } # all done! if ($verbose) { print STDERR "$progname: terminating\n"; } $dbi_counts->finish; $dbi_update->finish; $dbi_h->disconnect; exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/opendkim-rephistory.8.in000066400000000000000000000027611337314105200253670ustar00rootroot00000000000000.TH opendkim-rephistory 8 "The Trusted Domain Project" .SH NAME .B opendkim-rephistory \- OpenDKIM reputation history recording tool .SH SYNOPSIS .B opendkim-rephistory [options] .SH DESCRIPTION .B opendkim-rephistory copies the current reputation data for all domains into a history table to enable observation of the evolution of the reputations of domains over time. .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --expire=days Indicates the number of days of data to keep. The default is 180. .TP .I --help Prints a usage message and exits. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-rephistory that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011-2013, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-genrates(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/opendkim-rephistory.in000066400000000000000000000121521337314105200252140ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. # # Script to preserve current daily message and spam counts for each domain. # EXPERIMENTAL. ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::@SQL_BACKEND@; # general my $progname = basename($0); my $version = "\@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my $rows; my $maxage; my $dbi_h; my $dbi_s; my $def_maxage = 180; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "@SQL_BACKEND@"; ### ### NO user-serviceable parts beyond this point ### sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--expire=days expiration time, in days [$def_maxage]\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'expire=i' => \$maxage, 'help!' => \$helponly, 'verbose!' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # apply defaults if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } if (!defined($maxage)) { if (defined($ENV{'OPENDKIM_MAXAGE'})) { $maxage = $ENV{'OPENDKIM_MAXAGE'}; } else { $maxage = $def_maxage; } } # sanity check if ($maxage <= 0) { print STDERR "$progname: invalid expiration time\n"; exit(1); } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # Compute/update message counts and spam ratios for all signing domains # if ($verbose) { print STDERR "$progname: recording current reputation data for all domains\n"; } $dbi_s = $dbi_h->prepare("INSERT INTO history (date, domain, maxmsgs, maxspam, msglimit) SELECT DATE(NOW()), domain, rate_high, ratio_high, daily_limit_low FROM predictions WHERE DATE(updated) = DATE(NOW()) AND reporter = 0"); $rows = $dbi_s->execute(); if (!$rows) { print STDERR "$progname: INSERT/SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } elsif ($rows eq "0E0") { if ($verbose) { print STDOUT "$progname: no rows deleted\n"; } } else { if ($verbose) { print STDOUT "$progname: $rows row(s) added\n"; } } $dbi_s->finish; # # Expire messages # if ($verbose) { print STDERR "$progname: expiring records older than $maxage day(s)\n"; } $dbi_s = $dbi_h->prepare("DELETE FROM history WHERE date <= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL ? DAY)"); $rows = $dbi_s->execute($maxage); if (!$rows) { print STDERR "$progname: DELETE failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } elsif ($verbose) { if ($rows eq "0E0") { print STDOUT "$progname: no rows deleted\n"; } else { print STDOUT "$progname: $rows row(s) deleted\n"; } } # all done! if ($verbose) { print STDERR "$progname: terminating\n"; } $dbi_s->finish; $dbi_h->disconnect; exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/repute-config.php000066400000000000000000000005671337314105200241370ustar00rootroot00000000000000 OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/repute.c000066400000000000000000000430711337314105200223240ustar00rootroot00000000000000/* ** Copyright (c) 2011-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #ifdef USE_JANSSON /* libjansson includes */ # include #endif /* USE_JANSSON */ /* libcurl includes */ #include /* libut includes */ #include /* librepute includes */ #include "repute.h" /* limits */ #define REPUTE_BUFBASE 1024 #define REPUTE_URL 1024 #define REPUTE_TIMEOUT 10 /* data types */ struct repute_io { CURLcode repute_errcode; unsigned int repute_rcode; size_t repute_alloc; size_t repute_offset; char * repute_buf; struct repute_io * repute_next; CURL * repute_curl; }; struct repute_handle { unsigned int rep_reporter; pthread_mutex_t rep_lock; struct repute_io * rep_ios; const char * rep_server; const char * rep_useragent; const char * rep_curlversion; char rep_uritemp[REPUTE_URL + 1]; char rep_error[REPUTE_BUFBASE + 1]; }; /* globals */ static long timeout = REPUTE_TIMEOUT; /* ** REPUTE_CURL_WRITEDATA -- callback for libcurl to deliver data ** ** Parameters: ** ptr -- pointer to the retrieved data ** size -- unit size ** nmemb -- unit count ** userdata -- opaque userdata (points to a repute_io structure) ** ** Return value: ** Number of bytes taken in. If different from "size", libcurl reports ** an error. */ static size_t repute_curl_writedata(char *ptr, size_t size, size_t nmemb, void *userdata) { size_t need; struct repute_io *io; io = userdata; need = size * nmemb; if (io->repute_buf == NULL) { io->repute_alloc = MAX(REPUTE_BUFBASE, need); io->repute_buf = malloc(io->repute_alloc); if (io->repute_buf == NULL) return 0; memset(io->repute_buf, '\0', io->repute_alloc); } else if (io->repute_offset + need > io->repute_alloc) { size_t newsize; char *newbuf; newsize = MAX(io->repute_alloc * 2, io->repute_alloc + need); newbuf = realloc(io->repute_buf, newsize); if (newbuf == NULL) { return 0; } else { memset(newbuf + io->repute_offset, '\0', newsize - io->repute_offset); } io->repute_buf = newbuf; io->repute_alloc = newsize; } memcpy(io->repute_buf + io->repute_offset, ptr, need); io->repute_offset += need; return need; } /* ** REPUTE_PARSE -- parse a REPUTE message ** ** Parameters: ** buf -- buffer containing a REPUTE reply ** rep -- returned reputation ** conf -- confidence ** sample -- sample size ** limit -- recommented flow limit ** when -- timestamp on the report ** ** Return value: ** A REPUTE_STAT_* constant. */ static REPUTE_STAT repute_parse(const char *buf, size_t buflen, float *rep, float *conf, unsigned long *sample, unsigned long *limit, time_t *when) { _Bool found_dkim = FALSE; _Bool found_spam = FALSE; _Bool found_appl = FALSE; int code; float conftmp; float reptmp; unsigned long sampletmp; unsigned long limittmp; time_t whentmp; char *p; const char *start; #ifdef USE_JANSSON json_t *root = NULL; json_t *obj = NULL; json_t *reps = NULL; json_error_t error; #endif /* USE_JANSSON */ assert(buf != NULL); assert(rep != NULL); /* skip any header found */ /* XXX -- this should verify a desirable Content-Type */ for (start = buf; *start != '\0'; start++) { if (*start == '\n' && *(start + 1) == '\n') { buflen = buflen - (start - buf + 2); buf = start + 2; break; } else if (*start == '\r' && *(start + 1) == '\n' && *(start + 2) == '\r' && *(start + 3) == '\n') { buflen = buflen - (start - buf + 4); buf = start + 4; break; } } #ifdef USE_JANSSON root = json_loads(buf, 0, &error); if (root == NULL) return REPUTE_STAT_PARSE; obj = json_object_get(root, REPUTE_APPLICATION); if (obj != NULL && json_is_string(obj) && strcasecmp(json_string_value(obj), REPUTE_APPLICATION_VAL) == 0) found_appl = TRUE; reps = json_object_get(root, REPUTE_REPUTONS); if (reps != NULL && json_is_array(reps)) { int n; json_t *rep; for (n = 0; n < json_array_size(reps); n++) { rep = json_array_get(reps, n); obj = json_object_get(rep, REPUTE_ASSERTION); if (obj != NULL && json_is_string(obj) && strcasecmp(json_string_value(obj), REPUTE_ASSERT_SPAM) == 0) found_spam = TRUE; obj = json_object_get(rep, REPUTE_EXT_IDENTITY); if (obj != NULL && json_is_string(obj) && strcasecmp(json_string_value(obj), REPUTE_ID_DKIM) == 0) found_dkim = TRUE; obj = json_object_get(rep, REPUTE_EXT_RATE); if (obj != NULL && json_is_number(obj)) limittmp = (unsigned long) json_integer_value(obj); obj = json_object_get(rep, REPUTE_CONFIDENCE); if (obj != NULL && json_is_number(obj)) conftmp = (float) json_real_value(obj); obj = json_object_get(rep, REPUTE_RATING); if (obj != NULL && json_is_number(obj)) reptmp = (float) json_real_value(obj); obj = json_object_get(rep, REPUTE_SAMPLE_SIZE); if (obj != NULL && json_is_number(obj)) sampletmp = (unsigned long) json_integer_value(obj); obj = json_object_get(rep, REPUTE_GENERATED); if (obj != NULL && json_is_number(obj)) whentmp = (time_t) json_integer_value(obj); } } if (found_appl && found_dkim && found_spam) { *rep = reptmp; if (conf != NULL) *conf = conftmp; if (sample != NULL) *sample = sampletmp; if (when != NULL) *when = whentmp; if (limit != NULL) *limit = limittmp; } json_decref(root); #endif /* USE_JANSSON */ return REPUTE_STAT_OK; } /* ** REPUTE_GET_IO -- get or create an I/O handle ** ** Parameters: ** rep -- REPUTE handle ** ** Return value: ** An I/O handle if one could be either recycled or created, or NULL ** on failure. */ static struct repute_io * repute_get_io(REPUTE rep) { assert(rep != NULL); struct repute_io *rio = NULL; pthread_mutex_lock(&rep->rep_lock); if (rep->rep_ios != NULL) { rio = rep->rep_ios; rep->rep_ios = rep->rep_ios->repute_next; rio->repute_offset = 0; } else { rio = malloc(sizeof *rio); if (rio != NULL) { rio->repute_alloc = 0; rio->repute_offset = 0; rio->repute_buf = NULL; rio->repute_next = NULL; rio->repute_curl = curl_easy_init(); if (rio->repute_curl == NULL) { free(rio); rio = NULL; } else { int status; long longtmp; status = curl_easy_setopt(rio->repute_curl, CURLOPT_WRITEFUNCTION, repute_curl_writedata); if (status != CURLE_OK) { free(rio); rio = NULL; } if (rep->rep_useragent != NULL) { (void) curl_easy_setopt(rio->repute_curl, CURLOPT_USERAGENT, rep->rep_useragent); } longtmp = 1; (void) curl_easy_setopt(rio->repute_curl, CURLOPT_NOSIGNAL, longtmp); (void) curl_easy_setopt(rio->repute_curl, CURLOPT_TIMEOUT, timeout); } } } pthread_mutex_unlock(&rep->rep_lock); return rio; } /* ** REPUTE_PUT_IO -- recycle an I/O handle ** ** Parameters: ** rep -- REPUTE handle ** rio -- REPUTE I/O handle to be recycled ** ** Return value: ** None. */ static void repute_put_io(REPUTE rep, struct repute_io *rio) { assert(rep != NULL); assert(rio != NULL); pthread_mutex_lock(&rep->rep_lock); rio->repute_next = rep->rep_ios; rep->rep_ios = rio; pthread_mutex_unlock(&rep->rep_lock); } /* ** REPUTE_DOQUERY -- execute a query ** ** Parameters: ** ** Return value: ** A REPUTE_STAT_* constant. */ static REPUTE_STAT repute_doquery(struct repute_io *rio, const char *url) { CURLcode cstatus; long rcode; assert(rio != NULL); assert(url != NULL); cstatus = curl_easy_setopt(rio->repute_curl, CURLOPT_WRITEDATA, rio); if (cstatus != CURLE_OK) { rio->repute_errcode = cstatus; return REPUTE_STAT_INTERNAL; } cstatus = curl_easy_setopt(rio->repute_curl, CURLOPT_URL, url); if (cstatus != CURLE_OK) { rio->repute_errcode = cstatus; return REPUTE_STAT_INTERNAL; } rio->repute_errcode = 0; rio->repute_rcode = 0; memset(rio->repute_buf, '\0', rio->repute_alloc); cstatus = curl_easy_perform(rio->repute_curl); if (cstatus != CURLE_OK) { rio->repute_errcode = cstatus; return REPUTE_STAT_QUERY; } cstatus = curl_easy_getinfo(rio->repute_curl, CURLINFO_RESPONSE_CODE, &rcode); if (rcode != 200) return REPUTE_STAT_QUERY; return REPUTE_STAT_OK; } /* ** REPUTE_GET_ERROR -- retrieve an error string ** ** Parameters: ** rio -- repute I/O handle where an error occurred ** buf -- buffer to which to write the error string ** buflen -- bytes available at "buf" ** ** Return value: ** None. */ static void repute_get_error(struct repute_io *rio, char *buf, size_t buflen) { assert(rio != NULL); assert(buf != NULL); if (rio->repute_rcode != 0) snprintf(buf, buflen, "HTTP error code %u", rio->repute_rcode); else #ifdef HAVE_CURL_EASY_STRERROR snprintf(buf, buflen, curl_easy_strerror(rio->repute_errcode)); #else /* HAVE_CURL_EASY_STRERROR */ { snprintf(buf, buflen, "CURL error code %u", rio->repute_errcode); } #endif /* HAVE_CURL_EASY_STRERROR */ } /* ** REPUTE_GET_TEMPLATE -- retrieve a URI template for a service ** ** Parameters: ** rep -- REPUTE handle ** buf -- buffer into which to write the retrieved template ** buflen -- bytes available at "buf" ** ** Return value: ** A REPUTE_STAT_* constant. */ static int repute_get_template(REPUTE rep) { int cstatus; long rcode; struct repute_io *rio; URITEMP ut; char url[REPUTE_BUFBASE + 1]; assert(rep != NULL); ut = ut_init(); if (ut == NULL) return REPUTE_STAT_INTERNAL; if (ut_keyvalue(ut, UT_KEYTYPE_STRING, "scheme", REPUTE_URI_SCHEME) != 0 || ut_keyvalue(ut, UT_KEYTYPE_STRING, "service", (void *) rep->rep_server) != 0 || ut_keyvalue(ut, UT_KEYTYPE_STRING, "application", REPUTE_URI_APPLICATION) != 0) { ut_destroy(ut); return REPUTE_STAT_INTERNAL; } if (ut_generate(ut, REPUTE_URI_TEMPLATE, url, sizeof url) <= 0) { ut_destroy(ut); return REPUTE_STAT_INTERNAL; } ut_destroy(ut); rio = repute_get_io(rep); if (rio == NULL) return REPUTE_STAT_INTERNAL; cstatus = curl_easy_setopt(rio->repute_curl, CURLOPT_WRITEDATA, rio); if (cstatus != CURLE_OK) { #ifdef HAVE_CURL_EASY_STRERROR snprintf(rep->rep_error, sizeof rep->rep_error, "%s", curl_easy_strerror(cstatus)); #else /* HAVE_CURL_EASY_STRERROR */ snprintf(rep->rep_error, sizeof rep->rep_error, "CURL error code %d", cstatus); #endif /* HAVE_CURL_EASY_STRERROR */ repute_put_io(rep, rio); return REPUTE_STAT_INTERNAL; } cstatus = curl_easy_setopt(rio->repute_curl, CURLOPT_URL, url); if (cstatus != CURLE_OK) { #ifdef HAVE_CURL_EASY_STRERROR snprintf(rep->rep_error, sizeof rep->rep_error, "%s", curl_easy_strerror(cstatus)); #else /* HAVE_CURL_EASY_STRERROR */ snprintf(rep->rep_error, sizeof rep->rep_error, "CURL error code %d", cstatus); #endif /* HAVE_CURL_EASY_STRERROR */ repute_put_io(rep, rio); return REPUTE_STAT_INTERNAL; } cstatus = curl_easy_perform(rio->repute_curl); if (cstatus != CURLE_OK) { #ifdef HAVE_CURL_EASY_STRERROR snprintf(rep->rep_error, sizeof rep->rep_error, "%s", curl_easy_strerror(cstatus)); #else /* HAVE_CURL_EASY_STRERROR */ snprintf(rep->rep_error, sizeof rep->rep_error, "CURL error code %d", cstatus); #endif /* HAVE_CURL_EASY_STRERROR */ repute_put_io(rep, rio); return REPUTE_STAT_QUERY; } cstatus = curl_easy_getinfo(rio->repute_curl, CURLINFO_RESPONSE_CODE, &rcode); if (rcode != 200) { snprintf(rep->rep_error, sizeof rep->rep_error, "HTTP response code %u", (unsigned int) rcode); repute_put_io(rep, rio); return REPUTE_STAT_QUERY; } (void) snprintf(rep->rep_uritemp, sizeof rep->rep_uritemp, "%s", rio->repute_buf); if (rep->rep_uritemp[rio->repute_offset - 1] == '\n') rep->rep_uritemp[rio->repute_offset - 1] = '\0'; repute_put_io(rep, rio); return REPUTE_STAT_OK; } /* ** REPUTE_INIT -- initialize REPUTE subsystem ** ** Parameters: ** None. ** ** Return value: ** None. */ void repute_init(void) { curl_global_init(CURL_GLOBAL_ALL); } /* ** REPUTE_NEW -- make a new REPUTE handle ** ** Parameters: ** server -- server hostname ** reporter -- reporter ID to use ** ** Return value: ** A new REPUTE handle on success, NULL on failure. */ REPUTE repute_new(const char *server, unsigned int reporter) { struct repute_handle *new; curl_version_info_data *vinfo; assert(server != NULL); new = malloc(sizeof *new); if (new == NULL) return NULL; memset(new, '\0', sizeof *new); new->rep_reporter = reporter; new->rep_server = strdup(server); if (new->rep_server == NULL) { free(new); return NULL; } vinfo = curl_version_info(CURLVERSION_NOW); if (vinfo != NULL && vinfo->version != NULL) new->rep_curlversion = strdup(vinfo->version); pthread_mutex_init(&new->rep_lock, NULL); return new; } /* ** REPUTE_CLOSE -- tear down a REPUTE handle ** ** Paramters: ** rep -- REPUTE handle to shut down ** ** Return value: ** None. */ void repute_close(REPUTE rep) { struct repute_io *rio; struct repute_io *next; assert(rep != NULL); rio = rep->rep_ios; while (rio != NULL) { next = rio->repute_next; if (rio->repute_buf != NULL) free(rio->repute_buf); if (rio->repute_curl != NULL) curl_easy_cleanup(rio->repute_curl); free(rio); rio = next; } pthread_mutex_destroy(&rep->rep_lock); free((void *) rep->rep_server); free(rep); } /* ** REPUTE_CURLVERSION -- get libcurl version string ** ** Parameters: ** rep -- REPUTE handle ** ** Return value: ** A pointer to a string containing the libcurl version, or NULL. */ const char * repute_curlversion(REPUTE rep) { assert(rep != NULL); return rep->rep_curlversion; } /* ** REPUTE_USERAGENT -- set user agent for REPUTE queries ** ** Parameters: ** rep -- REPUTE handle ** ua -- User-Agent string to use ** ** Return value: ** None. */ void repute_useragent(REPUTE rep, const char *ua) { if (rep->rep_useragent != NULL) free((void *) rep->rep_useragent); rep->rep_useragent = strdup(ua); } /* ** REPUTE_QUERY -- query a REPUTE server for a spam reputation ** ** Parameters: ** rep -- REPUTE handle ** domain -- domain of interest ** repout -- reputation (returned) ** confout -- confidence (returned) ** sampout -- sample count (returned) ** limitout -- limit (returned) ** whenout -- update timestamp (returned) ** ** Return value: ** A REPUTE_STAT_* constant. */ REPUTE_STAT repute_query(REPUTE rep, const char *domain, float *repout, float *confout, unsigned long *sampout, unsigned long *limitout, time_t *whenout) { REPUTE_STAT status; float conf; float reputation; unsigned long samples; unsigned long limit; time_t when; struct repute_io *rio; URITEMP ut; char genurl[REPUTE_URL]; assert(rep != NULL); assert(domain != NULL); assert(repout != NULL); if (rep->rep_uritemp[0] == '\0') { if (repute_get_template(rep) != REPUTE_STAT_OK) return REPUTE_STAT_QUERY; } ut = ut_init(); if (ut == NULL) return REPUTE_STAT_INTERNAL; if (rep->rep_reporter != 0) { snprintf(genurl, sizeof genurl, "%u", rep->rep_reporter); if (ut_keyvalue(ut, UT_KEYTYPE_STRING, "reporter", genurl) != 0) { ut_destroy(ut); return REPUTE_STAT_INTERNAL; } } if (ut_keyvalue(ut, UT_KEYTYPE_STRING, "subject", (void *) domain) != 0 || #ifdef USE_JANSSON ut_keyvalue(ut, UT_KEYTYPE_STRING, "format", "json") != 0 || #endif /* USE_JANSSON */ ut_keyvalue(ut, UT_KEYTYPE_STRING, "scheme", REPUTE_URI_SCHEME) != 0 || ut_keyvalue(ut, UT_KEYTYPE_STRING, "service", (void *) rep->rep_server) != 0 || ut_keyvalue(ut, UT_KEYTYPE_STRING, "application", REPUTE_URI_APPLICATION) != 0 || ut_keyvalue(ut, UT_KEYTYPE_STRING, "assertion", REPUTE_ASSERT_SPAM) != 0) { ut_destroy(ut); return REPUTE_STAT_INTERNAL; } if (ut_generate(ut, rep->rep_uritemp, genurl, sizeof genurl) <= 0) { ut_destroy(ut); return REPUTE_STAT_INTERNAL; } ut_destroy(ut); rio = repute_get_io(rep); if (rio == NULL) return REPUTE_STAT_INTERNAL; status = repute_doquery(rio, genurl); if (status != REPUTE_STAT_OK) { repute_get_error(rio, rep->rep_error, sizeof rep->rep_error); repute_put_io(rep, rio); return status; } status = repute_parse(rio->repute_buf, rio->repute_offset, &reputation, &conf, &samples, &limit, &when); if (status != REPUTE_STAT_OK) { snprintf(rep->rep_error, sizeof rep->rep_error, "error parsing reply"); repute_put_io(rep, rio); return status; } *repout = reputation; if (confout != NULL) *confout = conf; if (sampout != NULL) *sampout = samples; if (whenout != NULL) *whenout = when; if (limitout != NULL) *limitout = limit; repute_put_io(rep, rio); return REPUTE_STAT_OK; } /* ** REPUTE_ERROR -- return a pointer to the error buffer ** ** Parameters: ** rep -- REPUTE handle ** ** Return value: ** Pointer to the error buffer inside the REPUTE handle. */ const char * repute_error(REPUTE rep) { assert(rep != NULL); return rep->rep_error; } /* ** REPUTE_SET_TIMEOUT -- set REPUTE query timeout ** ** Parameters: ** t -- timeout, in seconds ** ** Return value: ** None. */ void repute_set_timeout(long t) { timeout = t; } OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/repute.h000066400000000000000000000040021337314105200223200ustar00rootroot00000000000000/* ** Copyright (c) 2011-2013, The Trusted Domain Project. All rights reserved. */ #ifndef _REPUTE_H_ #define _REPUTE_H_ /* system includes */ #include #include /* constants */ #ifndef FALSE # define FALSE 0 #endif /* ! FALSE */ #ifndef TRUE # define TRUE 1 #endif /* ! TRUE */ /* status codes */ #define REPUTE_STAT_UNKNOWN (-1) /* unknown status */ #define REPUTE_STAT_OK 0 /* successful completion */ #define REPUTE_STAT_INTERNAL 1 /* internal error */ #define REPUTE_STAT_PARSE 2 /* parse failure */ #define REPUTE_STAT_QUERY 3 /* query failure */ #define REPUTE_CACHE 86400 /* XXX -- make this configurable */ typedef int REPUTE_STAT; /* constant strings */ #define REPUTE_NAME_REPUTATION "reputation" #define REPUTE_NAME_REPUTON "reputon" #define REPUTE_URI_APPLICATION "email-id" #define REPUTE_URI_SCHEME "http" #define REPUTE_URI_TEMPLATE "{scheme}://{service}/.well-known/repute-template" #define REPUTE_APPLICATION "application" #define REPUTE_REPUTONS "reputons" #define REPUTE_RATER "rater" #define REPUTE_ASSERTION "assertion" #define REPUTE_RATED "rated" #define REPUTE_RATING "rating" #define REPUTE_CONFIDENCE "confidence" #define REPUTE_SAMPLE_SIZE "sample-size" #define REPUTE_GENERATED "generated" #define REPUTE_EXT_IDENTITY "identity" #define REPUTE_EXT_RATE "rate" #define REPUTE_APPLICATION_VAL "email-id" #define REPUTE_ID_DKIM "dkim" #define REPUTE_ASSERT_SPAM "spam" /* other types */ struct repute_handle; typedef struct repute_handle * REPUTE; /* prototypes */ extern void repute_close(REPUTE); extern const char * repute_curlversion(REPUTE); extern const char *repute_error(REPUTE); extern void repute_init(void); extern REPUTE repute_new(const char *, unsigned int); extern REPUTE_STAT repute_query(REPUTE, const char *, float *, float *, unsigned long *, unsigned long *, time_t *); extern void repute_set_timeout(long); extern void repute_useragent(REPUTE, const char *); #endif /* ! _REPUTE_H_ */ OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/repute.pc.in000066400000000000000000000006511337314105200231060ustar00rootroot00000000000000# Process this file with autoconf to produce a pkg-config metadata file. prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: REPUTE query library Description: Library for performing REPUTE queries for spammy domains URL: http://opendkim.org Version: @VERSION@ Libs: -L${libdir} @PTHREAD_CFLAGS@ -lrepute Libs.private: @LIBRESOLV@ @PTHREAD_LIBS@ Cflags: -I${includedir} @PTHREAD_CFLAGS@ OpenDKIM-rel-opendkim-2-11-0-Beta2/reputation/repute.php000066400000000000000000000051331337314105200226660ustar00rootroot00000000000000 OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/000077500000000000000000000000001337314105200176135ustar00rootroot00000000000000OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/.gitignore000066400000000000000000000005571337314105200216120ustar00rootroot00000000000000*.o opendkim*.[58] *.lo *.la *.a *~ *.pc *.gcda *.gcno t-*[0-9] t-verifyperf t-signperf t-cleanup t-setup .deps/ .libs/ autom4te.cache/ autoscan-*.log build-config.h.in compile stamp-h* Makefile.in Makefile .deps .libs core *.core opendkim-anonstats opendkim-importstats opendkim-modtotals.pl opendkim-genstats opendkim-gengraphs opendkim-reportstats opendkim-expire OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/Makefile.am000066400000000000000000000014431337314105200216510ustar00rootroot00000000000000# Copyright (c) 2010-2014, The Trusted Domain Project. All rights reserved. exampledir = @docdir@ dist_example_DATA = mkdb.mysql dist_doc_DATA = README README.opendkim-reportstats dist_sbin_SCRIPTS = opendkim-expire opendkim-gengraphs opendkim-genstats \ opendkim-reportstats man_MANS = opendkim-expire.8 opendkim-gengraphs.8 opendkim-genstats.8 if USE_ODBX sbin_PROGRAMS = opendkim-importstats opendkim_importstats_SOURCES = opendkim-importstats.c opendkim_importstats_CPPFLAGS = $(LIBODBX_CPPFLAGS) -I$(srcdir)/../libopendkim -I$(srcdir)/../opendkim opendkim_importstats_CFLAGS = $(LIBODBX_CFLAGS) $(COV_CFLAGS) opendkim_importstats_LDFLAGS = $(LIBODBX_LDFLAGS) $(COV_LDFLAGS) opendkim_importstats_LDADD = $(LIBODBX_LIBS) $(LIBDL_LIBS) $(COV_LIBADD) man_MANS += opendkim-importstats.8 endif OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/README000066400000000000000000000240231337314105200204740ustar00rootroot00000000000000INTRODUCTION This is the development area for OpenDKIM's statistics collection system. In earlier versions, the statistics system gathered numerous details about messages and their DKIM signatures in order to produce a report about the observed implementation of DKIM on the Internet. The data recorded included the number of signatures, percent of signature failures, first-party vs. third-party signatures, ADSP statistics, etc. These data were collected and submitted to the Internet Engineering Task Force as part of a requirement to advance DKIM to Draft Standard status, and this work was very successful. As of v2.5.0, the statistics system has been repurposed to support ongoing research and development into open DKIM-based reputation services. The data collected has been drastically reduced to include only information about message arrival times, From domains, signing domains, sending IP addresses, and whether or not the message was reported as spam. You are invited, but certainly not required, to provide this information to The Trusted Domain Project. The code that does the reporting is open source and included in this package, so you can easily verify that nothing other than the above is being revealed in the data thus submitted. Participants that submit data will be invited to be part of an experimental reputation system based on DKIM that should begin to appear in the near future. This directory contains information and software for generating, receiving and processing such reports, including commands for creating a MySQL database to store the reports for later query, and a program that can receive reports generated by opendkim-stats to put such data directly into that database. INSTALLATION These instructions are for setting up your own reputation database and a feed to it. For instructions about providing a feed to an external service only, skip to the EXTERNAL FEEDS section. This system can be made to work with any SQL-based system, but the provided scripts and documentation presume MySQL. 1. Compile OpenDKIM using the "--enable-stats" option: % ./configure --enable-stats % make If you wish to apply local extensions to the statistics reporting system, see the EXTENSIONS section below. 2. Install MySQL. Create credentials for an "opendkim" user, optionally with some password. Create a database called "opendkim". Note that this does NOT refer to a "real" UNIX user and password. The user you create must be granted SELECT and INSERT access to that table. 3. From inside the MySQL client, source the "mkdb.mysql" script. This will create the tables required to store the statistics reports. 4. Install the "opendkim-stats" program someplace. 5. Configure OpenDKIM to have statistics enabled, and begin reporting them to a file someplace. This involves the "Statistics" setting. See the opendkim(8) and opendkim.conf(5) man pages for details. 6. Restart opendkim. 7a. To get a human-readable form of the recorded statistics, use: opendkim-stats /path/to/stats/file ...using, of course, the path to the statistics file you configure in opendkim.conf. You can reset the contents of that file at any time by simply removing it or copying /dev/null on top of it. The filter will create/append to the file on the next received message. 7b. To translate records in the recorded statistics file into SQL insert operations, use: opendkim-importstats /path/to/stats/file ...again using the path you specified in opendkim.conf. You will probably also need one or more of the following: -d dbname database name (default "opendkim") -p dbpasswd database user's password (no default) -s scheme database scheme (default "mysql") -u dbuser database user (default "opendkim") Append "-r" to this to remove the statistics file on completion. You can also use the provided opendkim-genstats script to generate useful reports from the accumulated data. Contribution of other reports you find useful would be welcome. 8. To participate in The Trusted Domain Project's data collection work, ask for the submission address you should use and then execute the following command: opendkim-reportstats -register This will generate a GPG signing key pair and send the public key to The Trusted Domain Project so your signatures can be verified. Upon receipt of your key, we will add it to our key ring, which will cause our system to begin trusting your reports. We will notify you when this has happened. Once this is done, you can arrange to have your cron job execute this command: opendkim-reportstats -sendstats This will send a signed copy of the current statistics data to The Trusted Domain Project and add the ".old" suffix to the filename. The filter will automatically start a new file when the next message is received.. When your data copy is received, The OpenDKIM project will use the aforementioned "opendkim-importstats" tool to import your data into the central database. You can view regularly generated reports, including your data, at: http://www.opendkim.org/stats/report.html EXTERNAL FEEDS If you are interested in producing statistics for the purpose of exporting them to a data aggregator other than yourself, follow steps 1 and 5, 6 and 8 above only. FILE FORMAT The format of the file written by the opendkim filter is described here. If demand appears, a stable API for accessing it will be provided. Until then, application developers are advised not to rely on this information being stable between versions. A statistics file consists of lines of ASCII data which are delimited from each other by a single LF (ASCII 10). Empty lines or lines beginning with other than alphabetic characters are ignored completely. A line in the file that begins with a capital letter identifies the type of record it represents. The first such line also implicitly ends the global values section. There are currently these record types: M identifies a message S identifies a signature U updates a message A message record is a tab-separated, ordered sequence of fields, as follows: MTA-provided job/envelope ID (string) reporter (string; defaults to hostname) first domain found in the From: header field (string) SMTP client IP address (string) UNIX timestamp of message receive time message size, in bytes signature count ATPS status (-1 = not checked, 0 = no, 1 = yes) spam status (-1 = not checked, 0 = no, 1 = yes) A signature record implicitly references the preceding message record. There may be more than one signature record per message; there could also be none. As above, a signature record is a tab-separated, ordered sequence of fields, as follows: domain of the signature pass (0 = no, 1 = yes) failed due to "bh" mismatch (0 = no, 1 = yes) "l=" tag value (-1 = not present) error code from signature DNSSEC value (see DKIM_DNSSEC_* constants from dkim.h) Fields for which no value is known or appropriate should be represented as "-" in the file. UPDATES As of v2.5.0, a "spam" column is present in the table tracking per-message information. When a batch of new message information is sent, this field is typically populated with a spam value of 0 (not spam). An update record can be sent later that changes the value in this column. The fields in this case are: MTA-provided job/envelope ID (string) reporter (string; defaults to hostname) UNIX timestamp of message receive time (0 if not known) spam indicator (-1 = not tested, 0 = not spam, 1 = spam) The first three fields must match those given for the corresponding "M" (new message) record at some time in the past. Where the timestamp is 0, the latest record matching the first two is updated. The "spam" column for that message will be replaced with the value found in the fourth field. EXTENSIONS For the purpose of allowing local experimentation, it is possible to extend the statistics reporting to include data about a message not covered by the basic schema distributed with OpenDKIM. Extension data are collected and stored during execution of the Lua "final" script and then written out to the stats file associated with that message. These items are written on "X" lines in the form "name value" (i.e. name and value separated by whitespace). opendkim-importstats will insert these into your database using "name" as the name of the column to be updated and "value" as the value to be placed there. Choosing the "--enable-statsext" flag at build configuration time adds support for this. The mechanism for recording these extra statistics is the odkim.stats() function, detailed in the opendkim-lua(3) man page. In this way, one can create any supplementary message-specific columns as is desirable and populate them whatever way is appropriate for each. Participants that find particular additional columns produce interesting correlations are encouraged to share them with the OpenDKIM community. CONVERTING TO THE IPADDRS SCHEMA In version 2.3.0 of OpenDKIM, the schema changed to add a new "ipaddrs" table, moving that data from each row of the "messages" table (causing duplication). The opendkim-importstats tool in 2.3.0 expects the new schema and is not back-compatible with prior releases. To convert your existing databases, use these steps: 1) Run the stats/mkdb.mysql script from inside your MySQL client to create the required new table. Existing tables will not be altered. 2) Run the following additional MySQL commands (lines are wrapped here for readability but each represents a single command): a) LOCK TABLES messages WRITE, ipaddrs WRITE; b) ALTER TABLE messages ADD COLUMN ip INT UNSIGNED AFTER ipaddr; c) INSERT INTO ipaddrs (addr, firstseen) SELECT DISTINCT ipaddr, MIN(msgtime) FROM messages GROUP BY ipaddr; d) UPDATE messages SET ip = (SELECT id FROM ipaddrs WHERE addr = messages.ipaddr); e) ALTER TABLE messages MODIFY COLUMN ip INT UNSIGNED NOT NULL, DROP COLUMN ipaddr, ADD CONSTRAINT FOREIGN KEY(ip) REFERENCES ipaddrs(id) ON DELETE CASCADE; f) UNLOCK TABLES; The various ALTER TABLE commands may require a rebuild of the "messages" table. This can take a large amount of time if the table is large. OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/README.opendkim-reportstats000066400000000000000000000056341337314105200247000ustar00rootroot00000000000000OPENDKIM REPORTSTATS README =========================== Please report any bugs to opendkim-users@lists.opendkim.org. There is a web site at http://www.opendkim.org that is home for the latest updates. +--------------+ | INTRODUCTION | +--------------+ The opendkim-reportstats script exists to help facilitate OpenDKIM statistics reporting. You are not required to use it and are welcome to roll your own. At some point, all statistics data sent to OpenDKIM will need to be PGP clear-signed to ensure there has been no tampering. This script well make the tasks of setup and automated reporting a fairly painless procedure. The script has two main flags: -register and -sendstats. While fairly self-explanatory the functions themselves are non-trivial. -register This steps through the process of obtaining the OpenDKIM public GPG key, creating your own unique public/private keypair and sending opendkim.org the public key encrypted. This is simply to ensure privacy. Only statistics reports that are clear-signed and verify will be accepted. The register process allows the OpenDKIM admin to selectively verify that sent statistics are from trusted users (regardless of the anonymity of the content). Once the OpenDKIM admin has validated your certificate and imported you will receive an email informing you that you may begin reporting. -sendregistration While the -register process sends your public key to opendkim.org, this flag will skip key import/generation in case there was a problem sending email the first time. Only use this if you were unable to send your registration with -register. -sendstats Once the registration process is over, this mode will (via cron or some other method) automatically clear-sign and send statistics to opendkim.org. Much effort has been made to make the script as generic and dynamic as possible, however due to the complexity of modern systems problems may still occur. Validating the dependencies listed below will help eliminate a good portion of foreseeable issues. This script has been written with two methodologies in mind: 1) If at any point a major problem is detected, stop. (Missing files, etc.) 2) Clobber temporary data so in the event that 1) happens, restarting should always be possible. Bug fixes and reports are always welcome. +--------------+ | DEPENDENCIES | +--------------+ For this script to operate properly the following are required: o OpenSSL (http://www.openssl.org, or ask your software vendor for a package). Any version will get you started, however v0.9.8 or later is recommended. o sendmail v8.13.0 (or later), or Postfix 2.3, (or later) and libmilter. (These are required for sending the statistics data.) o GNU wget ( http://www.gnu.org/software/wget/ ) or o cURL ( http://curl.haxx.se/ ) o GNU Privacy Guard (GNUPG) ( http://www.gnupg.org/ ) v1.4.10 or later -- Copyright (c) 2010, 2011, 2014, The Trusted Domain Project. All rights reserved. OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/mkdb.mysql000066400000000000000000000074001337314105200216200ustar00rootroot00000000000000 -- Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. -- MySQL command sequence to create a database to accumulate OpenDKIM -- statistics reports -- table of reporters create table if not exists reporters ( id int unsigned not null auto_increment, name varchar(255) not null, firstseen timestamp not null default CURRENT_TIMESTAMP, enabled tinyint not null default 1, primary key(id), unique key(name) ) engine=innodb default charset=latin1; -- table of domain names we've seen create table if not exists domains ( id int unsigned not null auto_increment, name varchar(255) not null, firstseen timestamp not null default CURRENT_TIMESTAMP, primary key(id), unique key(name) ) engine=innodb default charset=latin1; -- table of IP addresses we've seen create table if not exists ipaddrs ( id int unsigned not null auto_increment, addr varchar(64) not null, firstseen timestamp not null default CURRENT_TIMESTAMP, primary key(id), unique key(addr) ) engine=innodb default charset=latin1; -- table of messages names we've seen create table if not exists messages ( id int unsigned not null auto_increment, jobid varchar(64) not null, reporter int unsigned not null, from_domain int unsigned not null, ip int unsigned not null, msgtime timestamp not null default CURRENT_TIMESTAMP, size int unsigned not null, sigcount int unsigned not null, spam tinyint not null default -1, atps tinyint not null default -1, primary key(id), key(reporter), key(from_domain), key(ip), key(msgtime), unique key(reporter, jobid, msgtime), foreign key(from_domain) references domains(id) on delete cascade, foreign key(ip) references ipaddrs(id) on delete cascade, foreign key(reporter) references reporters(id) on delete cascade ) engine=innodb default charset=latin1; -- table of signatures we've seen create table if not exists signatures ( id int unsigned not null auto_increment, message int unsigned not null, domain int unsigned not null, pass tinyint unsigned not null, fail_body tinyint unsigned not null, siglength int not null, sigerror tinyint unsigned not null, dnssec tinyint not null, primary key(id), key(domain), foreign key(message) references messages(id) on delete cascade, foreign key(domain) references domains(id) on delete cascade ) engine=innodb default charset=latin1; -- table mapping signature error codes to descriptions create table if not exists sigerrorcodes ( id tinyint not null, name varchar(255) not null, primary key (id) ) engine=innodb default charset=latin1; insert ignore into sigerrorcodes (id, name) values (-1, "unknown error"), (0, "no error"), (1, "unsupported version"), (2, "invalid domain (d=/i=)"), (3, "signature expired"), (4, "signature in the future"), (5, "x= < t="), (6, "c= missing"), (7, "c= invalid (header)"), (8, "c= invalid (body)"), (9, "a= missing"), (10, "a= invalid"), (11, "h= missing"), (12, "l= invalid"), (13, "q= invalid"), (14, "q= option invalid"), (15, "d= missing"), (16, "d= empty"), (17, "s= missing"), (18, "s= empty"), (19, "b= missing"), (20, "b= empty"), (21, "b= corrupt"), (22, "no key found in DNS"), (23, "DNS reply corrupt"), (24, "DNS query failed"), (25, "bh= missing"), (26, "bh= empty"), (27, "bh= corrupt"), (28, "signature mismatch"), (29, "unauthorized subdomain"), (30, "multiple records returned"), (31, "h= empty"), (32, "h= missing required entries"), (33, "l= value exceeds body size"), (34, "field-must-be-signed failure"), (35, "unknown key version"), (36, "unknown key hash"), (37, "signature-key hash mismatch"), (38, "not an email key"), (39, "key granularity mismatch"), (40, "key type missing"), (41, "key type unknown"), (42, "key revoked"), (43, "key could not be decoded"), (44, "v= missing"), (45, "v= empty") ; OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-expire.8.in000066400000000000000000000026021337314105200234110ustar00rootroot00000000000000.TH opendkim-expire 8 "The Trusted Domain Project" .SH NAME .B opendkim-expire \- OpenDKIM statistics data expiration tool .SH SYNOPSIS .B opendkim-expire [options] .SH DESCRIPTION .B opendkim-expire expires old records from the database that is part of the OpenDKIM statistics feature. .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --expire=days Indicates the number of days of data to keep. The default is 180. .TP .I --help Prints a usage message and exits. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-expire that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-expire.in000066400000000000000000000135051337314105200232470ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # # # Script to age out OpenDKIM statistics data ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::mysql; # general my $progname = basename($0); my $version = "@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my $minmsg; my $dbi_s; my $dbi_h; my $dbi_a; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "mysql"; my $def_maxage = 180; my $rows; my $maxage; ### ### NO user-serviceable parts beyond this point ### sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--expire=days expiration time, in days [$def_maxage]\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'expire=i' => \$maxage, 'help!' => \$helponly, 'verbose!' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # apply defaults if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } if (!defined($maxage)) { if (defined($ENV{'OPENDKIM_MAXAGE'})) { $maxage = $ENV{'OPENDKIM_MAXAGE'}; } else { $maxage = $def_maxage; } } # sanity check if ($maxage <= 0) { print STDERR "$progname: invalid expiration time\n"; exit(1); } # # Let's go! # if ($verbose) { print STDERR "$progname: started at " . localtime() . "\n"; } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # Expire messages # if ($verbose) { print STDERR "$progname: expiring messages older than $maxage day(s)\n"; } $dbi_s = $dbi_h->prepare("DELETE FROM messages WHERE msgtime <= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL ? DAY)"); $rows = $dbi_s->execute($maxage); if (!$rows) { print STDERR "$progname: DELETE failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } elsif ($verbose) { if ($rows eq "0E0") { print STDOUT "$progname: no rows deleted\n"; } else { print STDOUT "$progname: $rows row(s) deleted\n"; } } $dbi_s->finish; # # Expire signatures # $dbi_s = $dbi_h->prepare("SELECT MIN(id) FROM messages"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { $minmsg = $dbi_a->[0]; } $dbi_s->finish; if ($verbose) { print STDERR "$progname: expiring signatures on expired messages (id < $minmsg)\n"; } $dbi_s = $dbi_h->prepare("DELETE FROM signatures WHERE message < ?"); $rows = $dbi_s->execute($minmsg); if (!$rows) { print STDERR "$progname: DELETE failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } elsif ($verbose) { if ($rows eq "0E0") { print STDOUT "$progname: no rows deleted\n"; } else { print STDOUT "$progname: $rows row(s) deleted\n"; } } $dbi_s->finish; # # Expire aggregate data # if ($verbose) { print STDERR "$progname: expiring aggregate data older than $maxage days\n"; } $dbi_s = $dbi_h->prepare("DELETE FROM aggregate WHERE date <= DATE_SUB(CURRENT_TIMESTAMP(), INTERVAL ? DAY)"); $rows = $dbi_s->execute($maxage); if (!$rows) { print STDERR "$progname: DELETE failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } elsif ($verbose) { if ($rows eq "0E0") { print STDOUT "$progname: no rows deleted\n"; } else { print STDOUT "$progname: $rows row(s) deleted\n"; } } $dbi_s->finish; # # All done! # if ($verbose) { print STDERR "$progname: terminating at " . localtime() . "\n"; } $dbi_h->disconnect; exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-gengraphs.8.in000066400000000000000000000040701337314105200240740ustar00rootroot00000000000000.TH opendkim-gengraphs 8 "The Trusted Domain Project" .SH NAME .B opendkim-gengraphs \- OpenDKIM statistics graph generation tool .SH SYNOPSIS .B opendkim-gengraphs [options] .SH DESCRIPTION .B opendkim-gengraphs collates data accumulated by the OpenDKIM statistics feature into an HTML report including graphs about the daily behaviour of specific domains of interest. Requires access to .B gnuplot(1). .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --domain={ domain | file } Adds the named .I domain, or domains extracted from the named .I file, to the set of domains for which a graph should be generated. Strings that start with "/" or "./" are assumed to be files from which domain naems should be read. .TP .I --help Prints a usage message and exits. .TP .I --nocircles Prevents the script from requesting circles in graphs to show point magnitude (also known as a bubble graph) for installations that have versions of .B gnuplot(1) that don't support it. .TP .I --nounsigned Suppresses generation of a graph for unsigned mail. .TP .I --output=file Writes an HTML report to the specified .I file. Graphs will be generated in the same directory. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-gengraphs that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-gengraphs.in000066400000000000000000000300651337314105200237310ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # # # Script to generate some graphs showing DKIM stats for some domains ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::mysql; # general my $progname = basename($0); my $version = "\@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my $out; my $reportdir; my $datafile; my $pngfile; my $anchor; my $domain; my $tmpdom; my $dbi_s; my $dbi_h; my $dbi_a; my $unsigned = 1; my $circles = 1; my $circlestr; my $idx; my $tmpin; my @domains; my @xdata; my @ydata; my @zdata; my %yhash; my $plot; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "mysql"; # output location (default) my $reportout; my $tmpout; ### ### NO user-serviceable parts beyond this point ### sub make_temporary_table { $dbi_s = $dbi_h->prepare("CREATE TEMPORARY TABLE t1 ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, ddate DATE, msgcount INT UNSIGNED NOT NULL, spamcount INT UNSIGNED NOT NULL, domain VARCHAR(255) NOT NULL, PRIMARY KEY(id), KEY(domain) )"); if (!$dbi_s->execute) { print STDERR "$progname: CREATE TEMPORARY TABLE failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; } sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--domain=name domain(s) on which to report\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--nocircles don't tell gnuplot to use circles\n"; print STDERR "\t--output=file output file\n"; print STDERR "\t--unsigned report about unsigned mail\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('circles!' => \$circles, 'dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'domain=s@' => \@domains, 'help!' => \$helponly, 'output=s' => \$reportout, 'unsigned!' => \$unsigned, 'verbose!' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # apply defaults if ($circles) { $circlestr = "with circles"; } else { $circlestr = ""; } if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } if (!defined($reportout)) { if (defined($ENV{'OPENDKIM_OUTPUT'})) { $reportout = $ENV{'OPENDKIM_OUTPUT'}; } } if ($verbose) { print STDERR "$progname: started at " . localtime() . "\n"; } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # If any of the domains started with "/" or "./", convert them into # whatever's in the files they reference. # if (scalar @domains > 0) { foreach $idx (0 .. $#domains) { if (substr($domains[$idx], 0, 1) eq "/" || substr($domains[$idx], 0, 2) eq "./") { if (!open($tmpin, "<", $domains[$idx])) { print STDERR "$progname: cannot open $domains[$idx]: $!\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while (<$tmpin>) { # ignore comments s/#.*//; # ignore blank lines next if /^(\s)*$/; chomp; push @domains, $_; } close($tmpin); delete $domains[$idx]; } } } # # start the report # if (!defined($reportout)) { print STDERR "$progname: no output selected\n"; exit(1); } $reportdir = dirname($reportout); $tmpout = $reportout . "." . $$; open($out, ">", $tmpout) or die "$progname: can't open $tmpout: $!"; if ($verbose) { print STDERR "$progname: report started in $tmpout\n"; } print $out "\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " OpenDKIM Data Per Domain\n"; print $out " \n"; print $out " \n"; print $out "\n"; print $out " \n"; print $out "

OpenDKIM Data Per Domain

\n"; print $out "Generated " . strftime("%b %e %Y %H:%M:%S", localtime) . "\n"; print $out "
\n"; print $out "
    \n"; if (scalar @domains > 0) { foreach $domain (@domains) { if (!defined($domain)) { next; } $tmpdom = $domain; $tmpdom =~ s/\./_/; print $out "
  • " . $domain . "\n"; } } if ($unsigned) { print $out "
  • Unsigned Mail\n"; } print $out "
\n"; print $out "
\n"; # # build a temporary table # if ($verbose) { print STDERR "$progname: constructing temporary table\n"; } make_temporary_table(); if ($verbose) { print STDERR "$progname: populating temporary table\n"; } $dbi_s = $dbi_h->prepare("INSERT INTO t1 ( ddate, msgcount, spamcount, domain) SELECT DATE(messages.msgtime), COUNT(messages.id), SUM(messages.spam), domains.name FROM messages JOIN reporters ON reporters.id = messages.reporter JOIN signatures ON messages.id = signatures.message JOIN domains ON domains.id = signatures.domain WHERE reporters.enabled = 1 AND signatures.pass = 1 AND NOT messages.spam = -1 GROUP BY signatures.domain, DATE(messages.msgtime)"); if (!$dbi_s->execute) { print STDERR "$progname: INSERT INTO TEMPORARY TABLE failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; $dbi_s = $dbi_h->prepare("SELECT msgcount, spamcount, 1+LOG10(COUNT(id)) FROM t1 WHERE domain = ? GROUP BY 1, 2"); $datafile = $reportdir . "/ogg.data." . $$; $pngfile = $reportdir . "/ogg.png." . $$; if (scalar @domains > 0) { foreach $domain (@domains) { if (!defined($domain)) { next; } if ($verbose) { print STDERR "$progname: reporting for $domain\n"; } $tmpdom = $domain; $tmpdom =~ s/\./_/; print $out "" . $domain . ":\n"; print $out "
\n"; if (!$dbi_s->execute($domain)) { print STDERR "$progname: domain report for " . $domain . " failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } open(GNUDATA, ">" . $datafile) or die $progname . ": can't create temporary file $datafile\n"; while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print GNUDATA $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "\n"; } $dbi_s->finish; close GNUDATA; open(GNUPLOT, "|gnuplot > /dev/null 2>&1") or die $progname . ": can't execute gnuplot\n"; print GNUPLOT "set xrange [0:*]\n"; print GNUPLOT "set yrange [0:*]\n"; print GNUPLOT "unset log\n"; print GNUPLOT "unset label\n"; print GNUPLOT "set xtic auto\n"; print GNUPLOT "set ytic auto\n"; print GNUPLOT "set xlabel 'received'\n"; print GNUPLOT "set ylabel 'spam'\n"; print GNUPLOT "set terminal png size 800,600\n"; print GNUPLOT "set title '" . $domain . " received-spam scatter plot'\n"; print GNUPLOT "set output '$pngfile'\n"; print GNUPLOT "plot '$datafile' using 1:2:3 notitle $circlestr\n"; close(GNUPLOT); rename($pngfile, $reportdir . "/" . $domain . ".png"); unlink($datafile); print $out "\n"; print $out "
\n"; } } if ($unsigned) { $dbi_s = $dbi_h->prepare("DROP TEMPORARY TABLE t1\n"); if (!$dbi_s->execute) { print STDERR "$progname: DROP TEMPORARY TABLE failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; make_temporary_table(); if ($verbose) { print STDERR "$progname: repopulating temporary table for unsigned mail\n"; } $dbi_s = $dbi_h->prepare("INSERT INTO t1 ( ddate, msgcount, spamcount, domain) SELECT DATE(messages.msgtime), COUNT(messages.id), SUM(messages.spam), 'UNSIGNED' FROM messages JOIN reporters ON reporters.id = messages.reporter JOIN signatures ON messages.id = signatures.message WHERE reporters.enabled = 1 AND NOT messages.spam = -1 AND NOT messages.id IN (SELECT DISTINCT message FROM signatures WHERE pass = 1) GROUP BY DATE(messages.msgtime)"); if (!$dbi_s->execute) { print STDERR "$progname: INSERT INTO TEMPORARY TABLE failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; if ($verbose) { print STDERR "$progname: reporting for unsigned mail\n"; } $dbi_s = $dbi_h->prepare("SELECT msgcount, spamcount, 1+LOG10(COUNT(id)) FROM t1 GROUP BY 1, 2"); if (!$dbi_s->execute) { print STDERR "$progname: domain report for unsigned mail failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } open(GNUDATA, ">" . $datafile) or die $progname . ": can't create temporary file $datafile\n"; while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print GNUDATA $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "\n"; } $dbi_s->finish; close GNUDATA; print $out "\n"; print $out "

unsigned mail:

\n"; open(GNUPLOT, "|gnuplot > /dev/null 2>&1") or die $progname . ": can't execute gnuplot\n"; print GNUPLOT "set xrange [0:*]\n"; print GNUPLOT "set yrange [0:*]\n"; print GNUPLOT "unset log\n"; print GNUPLOT "unset label\n"; print GNUPLOT "set xtic auto\n"; print GNUPLOT "set ytic auto\n"; print GNUPLOT "set xlabel 'received'\n"; print GNUPLOT "set ylabel 'spam'\n"; print GNUPLOT "set terminal png size 800,600\n"; print GNUPLOT "set title 'unsigned received-spam scatter plot'\n"; print GNUPLOT "set output '$pngfile'\n"; print GNUPLOT "plot '$datafile' using 1:2:3 notitle $circlestr\n"; close(GNUPLOT); rename($pngfile, $reportdir . "/unsigned.png"); unlink($datafile); print $out "\n"; } # # all done! # print $out " \n"; print $out "\n"; if ($verbose) { print STDERR "$progname: terminating at " . localtime() . "\n"; } $dbi_h->disconnect; if (defined($reportout)) { close $out; rename($tmpout, $reportout) or die "$progname: rename to $reportout failed; $!"; } exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-genstats.8.in000066400000000000000000000025661337314105200237560ustar00rootroot00000000000000.TH opendkim-genstats 8 "The Trusted Domain Project" .SH NAME .B opendkim-genstats \- OpenDKIM statistics report generation tool .SH SYNOPSIS .B opendkim-genstats [options] .SH DESCRIPTION .B opendkim-genstats collates data accumulated by the OpenDKIM statistics feature into an HTML report. .SH OPTIONS .TP .I --dbhost=host Attempts to connect to the database server on the named .I host. The default is "localhost". .TP .I --dbname=name Requests a connection to the database called .I name. The default is "opendkim". .TP .I --dbpasswd=password Attempts to authenticate to the database server using the specified .I password. The default is "opendkim". .TP .I --dbport=port Tries to connect to the database at the specified TCP .I port. The default is 3306. .TP .I --dbuser=user Attempts to authenticate to the database server as the specified .I user. The default is "opendkim". .TP .I --help Prints a usage message and exits. .TP .I --output=file Writes an HTML report to the specified .I file. .TP .I --verbose Requests verbose output. .TP .I --version Prints version number and exits. .SH VERSION This man page covers the version of .I opendkim-genstats that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2011, 2012, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim-importstats(8) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-genstats.in000066400000000000000000000571141337314105200236070ustar00rootroot00000000000000#!/usr/bin/perl # # Copyright (c) 2010-2012, The Trusted Domain Project. All rights reserved. # # Script to generate some HTML-ized statistics for OpenDKIM ### ### Setup ### use strict; use warnings; use DBI; use File::Basename; use Getopt::Long; use IO::Handle; use POSIX; require DBD::mysql; # general my $progname = basename($0); my $version = "@VERSION@"; my $verbose = 0; my $helponly = 0; my $showversion = 0; my $out; my $idx; my $dbi_s; my $dbi_h; my $dbi_a; my $thresh; # DB parameters my $def_dbhost = "localhost"; my $def_dbname = "opendkim"; my $def_dbuser = "opendkim"; my $def_dbpasswd = "opendkim"; my $def_dbport = "3306"; my $dbhost; my $dbname; my $dbuser; my $dbpasswd; my $dbport; my $dbscheme = "mysql"; # output location (default) my $reportout; my $tmpout; ### ### NO user-serviceable parts beyond this point ### sub usage { print STDERR "$progname: usage: $progname [options]\n"; print STDERR "\t--dbhost=host database host [$def_dbhost]\n"; print STDERR "\t--dbname=name database name [$def_dbname]\n"; print STDERR "\t--dbpasswd=passwd database password [$def_dbpasswd]\n"; print STDERR "\t--dbport=port database port [$def_dbport]\n"; print STDERR "\t--dbuser=user database user [$def_dbuser]\n"; print STDERR "\t--help print help and exit\n"; print STDERR "\t--output=file output file\n"; print STDERR "\t--verbose verbose output\n"; print STDERR "\t--version print version and exit\n"; } # parse command line arguments my $opt_retval = &Getopt::Long::GetOptions ('dbhost=s' => \$dbhost, 'dbname=s' => \$dbname, 'dbpasswd=s' => \$dbpasswd, 'dbport=s' => \$dbport, 'dbuser=s' => \$dbuser, 'help!' => \$helponly, 'output=s' => \$reportout, 'verbose!' => \$verbose, 'version!' => \$showversion, ); if (!$opt_retval || $helponly) { usage(); if ($helponly) { exit(0); } else { exit(1); } } if ($showversion) { print STDOUT "$progname v$version\n"; exit(0); } # apply defaults if (!defined($dbhost)) { if (defined($ENV{'OPENDKIM_DBHOST'})) { $dbhost = $ENV{'OPENDKIM_DBHOST'}; } else { $dbhost = $def_dbhost; } } if (!defined($dbname)) { if (defined($ENV{'OPENDKIM_DB'})) { $dbname = $ENV{'OPENDKIM_DB'}; } else { $dbname = $def_dbname; } } if (!defined($dbpasswd)) { if (defined($ENV{'OPENDKIM_PASSWORD'})) { $dbpasswd = $ENV{'OPENDKIM_PASSWORD'}; } else { $dbpasswd = $def_dbpasswd; } } if (!defined($dbport)) { if (defined($ENV{'OPENDKIM_PORT'})) { $dbport = $ENV{'OPENDKIM_PORT'}; } else { $dbport = $def_dbport; } } if (!defined($dbuser)) { if (defined($ENV{'OPENDKIM_USER'})) { $dbuser = $ENV{'OPENDKIM_USER'}; } else { $dbuser = $def_dbuser; } } if (!defined($reportout)) { if (defined($ENV{'OPENDKIM_OUTPUT'})) { $reportout = $ENV{'OPENDKIM_OUTPUT'}; } } if ($verbose) { print STDERR "$progname: started at " . localtime() . "\n"; } my $dbi_dsn = "DBI:" . $dbscheme . ":database=" . $dbname . ";host=" . $dbhost . ";port=" . $dbport; $dbi_h = DBI->connect($dbi_dsn, $dbuser, $dbpasswd, { PrintError => 0 }); if (!defined($dbi_h)) { print STDERR "$progname: unable to connect to database: $DBI::errstr\n"; exit(1); } if ($verbose) { print STDERR "$progname: connected to database\n"; } # # start the report # if (!defined($reportout)) { print STDERR "$progname: no output selected\n"; exit(1); } $tmpout = $reportout . "." . $$; open($out, ">", $tmpout) or die "$progname: can't open $tmpout: $!"; if ($verbose) { print STDERR "$progname: report started in $tmpout\n"; } print $out "\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " OpenDKIM Statistics Report\n"; print $out " \n"; print $out " \n"; print $out "\n"; print $out " \n"; print $out "

OpenDKIM Statistics Report

\n"; print $out "Generated " . strftime("%b %e %Y %H:%M:%S", localtime) . "\n"; print $out "
\n"; print $out "\n"; print $out "
\n"; # # build a temporary table # if ($verbose) { print STDERR "$progname: constructing temporary table\n"; } $dbi_s = $dbi_h->prepare("CREATE TEMPORARY TABLE t1 ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, messages_id INT UNSIGNED NOT NULL, messages_date TIMESTAMP NOT NULL, messages_from_domain INT UNSIGNED NOT NULL, messages_atps TINYINT UNSIGNED NOT NULL, messages_sigcount SMALLINT UNSIGNED NOT NULL, signatures_id INT UNSIGNED NOT NULL, signatures_domain INT UNSIGNED NOT NULL, signatures_pass TINYINT UNSIGNED NOT NULL, signatures_fail_body TINYINT UNSIGNED NOT NULL, signatures_sigerror SMALLINT UNSIGNED NOT NULL, signatures_dnssec SMALLINT NOT NULL, reporters_id INT UNSIGNED NOT NULL, reporters_name VARCHAR(255) NOT NULL, reporters_firstseen TIMESTAMP NOT NULL, PRIMARY KEY(id), KEY(messages_from_domain), KEY(messages_sigcount), KEY(messages_atps), KEY(signatures_domain), KEY(signatures_dnssec), KEY(reporters_id) )"); if (!$dbi_s->execute) { print STDERR "$progname: CREATE TEMPORARY TABLE failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; if ($verbose) { print STDERR "$progname: populating temporary table\n"; } $dbi_s = $dbi_h->prepare("INSERT INTO t1 ( messages_id, messages_date, messages_from_domain, messages_atps, messages_sigcount, signatures_id, signatures_domain, signatures_pass, signatures_fail_body, signatures_sigerror, signatures_dnssec, reporters_id, reporters_name, reporters_firstseen) SELECT messages.id, messages.msgtime, messages.from_domain, messages.atps, messages.sigcount, signatures.id, signatures.domain, signatures.pass, signatures.fail_body, signatures.sigerror, signatures.dnssec, reporters.id, reporters.name, reporters.firstseen FROM messages JOIN reporters ON messages.reporter = reporters.id LEFT OUTER JOIN signatures ON signatures.message = messages.id WHERE reporters.enabled = 1"); if (!$dbi_s->execute) { print STDERR "$progname: INSERT INTO TEMPORARY TABLE failed: " . $dbi_h->errstr . "\n"; $dbi_s->finish; $dbi_h->disconnect; exit(1); } $dbi_s->finish; if ($verbose) { print STDERR "$progname: generating reports\n"; } # # Total record count # print $out "\n"; print $out "

Total records (messages) received:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT messages_id), SUM(SIGN(messages_sigcount)) FROM t1"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Messages Signed
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Reporting hosts # print $out "\n"; print $out "

Reporting hosts and record counts:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT reporters_name, COUNT(DISTINCT messages_id), reporters_firstseen, MAX(messages_date) FROM t1 GROUP BY 1 ORDER BY 2"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Reporter Messages Since Last
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . " " . $dbi_a->[3] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Overall message signature counts # print $out "\n"; print $out "

Overall message signature counts:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT messages_sigcount, COUNT(DISTINCT messages_id) FROM t1 GROUP BY 1"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Signatures Messages
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # DNSSEC results # print $out "\n"; print $out "

DNSSEC results (see libopendkim/dkim.h):

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT signatures_dnssec, COUNT(id) FROM t1 GROUP BY 1 ORDER BY 1"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
DNSSEC code Signature Count
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # DNSSEC trend # print $out "\n"; print $out "

DNSSEC trend:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT signatures_domain), YEAR(messages_date), MONTHNAME(messages_date) FROM t1 WHERE (signatures_dnssec = 0 OR signatures_dnssec = 2) GROUP BY 2, 3 ORDER BY 2, MONTH(messages_date)"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Domains Year Month
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Pass/fail rates # print $out "\n"; print $out "

Overall pass/fail rate for signed mail:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT signatures_id), SUM(signatures_pass), SUM(signatures_fail_body) FROM t1 WHERE signatures_id IS NOT NULL"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Signatures Passed Failed (body)
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Top error codes # print $out "\n"; print $out "

Top ten error codes (see libopendkim/dkim.h):

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT sigerrorcodes.name, COUNT(t1.id) FROM t1 JOIN sigerrorcodes ON sigerrorcodes.id = signatures_sigerror WHERE NOT signatures_sigerror IN (0, 28) GROUP BY signatures_sigerror ORDER BY 2 DESC LIMIT 10"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Error Instances
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Author vs. third-party, non-MLM # print $out "\n"; print $out "

Author vs. third-party signatures, non-MLM traffic:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT signatures_id), SUM(signatures_pass) FROM t1 WHERE messages_from_domain = signatures_domain"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Author Signatures Passed
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT signatures_id), SUM(signatures_pass) FROM t1 WHERE NOT messages_from_domain = signatures_domain"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Third-Party Signatures Passed
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Unique signed From: domains # print $out "\n"; print $out "

Count of unique signed From: domains in sample:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT messages_from_domain) FROM t1 WHERE messages_sigcount > 0"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Domains
" . $dbi_a->[0] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Top 10 signing domains by signature count # print $out "\n"; print $out "

Top 10 signing domains by signature count:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT domains.name, SUM(messages_sigcount) FROM t1 JOIN domains ON t1.signatures_domain = domains.id GROUP BY t1.signatures_domain ORDER BY 2 DESC LIMIT 10"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Domain Signatures
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Top 10 passing domains # print $out "\n"; print $out "

Top 10 signing domains by passing signature percentage:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT domains.name, COUNT(t1.id), 100*SUM(t1.signatures_pass)/COUNT(t1.id) FROM t1 JOIN domains ON t1.signatures_domain = domains.id GROUP BY t1.signatures_domain ORDER BY 3 DESC, 2 DESC LIMIT 10"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Domain Signatures % Passed
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Top 10 failing domains # print $out "\n"; print $out "

Top 10 signing domains by failing signature percentage:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT domains.name, COUNT(t1.id), 100-100*SUM(signatures_pass)/COUNT(t1.id) FROM t1 JOIN domains ON t1.signatures_domain = domains.id GROUP BY t1.signatures_domain ORDER BY 3 DESC, 2 DESC LIMIT 10"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Domain Signatures % Failed
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Domain use counts # print $out "\n"; print $out "

Signing domain use counts:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT msgcount, COUNT(signatures_domain) FROM (SELECT signatures_domain, COUNT(id) AS msgcount FROM t1 GROUP BY 1) a GROUP BY 1 ORDER BY 1 ASC LIMIT 10"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Messages Domains
" . $dbi_a->[0] . " " . $dbi_a->[1] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Signing trend (messages) # print $out "\n"; print $out "

Trend in message signing rates:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT YEAR(messages_date), MONTHNAME(messages_date), (100. * SUM(SIGN(messages_sigcount)) / COUNT(DISTINCT messages_id)) FROM t1 GROUP BY 1, MONTH(messages_date) ORDER BY 1, MONTH(messages_date)"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Year Month % Signed
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "
\n"; print $out "
\n"; $dbi_s->finish; # # Signing trend (domains) # print $out "\n"; print $out "

Trend in message signing rates:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT YEAR(messages_date), MONTHNAME(messages_date), COUNT(DISTINCT signatures_domain) FROM t1 GROUP BY 1, MONTH(messages_date) ORDER BY 1, MONTH(messages_date)"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Year Month Domains
" . $dbi_a->[0] . " " . $dbi_a->[1] . " " . $dbi_a->[2] . "
\n"; print $out "
\n"; $dbi_s->finish; # # ATPS use # print $out "\n"; print $out "

ATPS use:

\n"; print $out "\n"; print $out " \n"; print $out " \n"; print $out " \n"; $dbi_s = $dbi_h->prepare("SELECT COUNT(DISTINCT messages_from_domain) FROM t1 WHERE messages_atps = 1"); if (!$dbi_s->execute) { print STDERR "$progname: SELECT failed: " . $dbi_h->errstr; $dbi_s->finish; $dbi_h->disconnect; exit(1); } while ($dbi_a = $dbi_s->fetchrow_arrayref()) { print $out " \n"; print $out " \n"; print $out " \n"; } print $out "
Domains
" . $dbi_a->[0] . "
\n"; print $out "
\n"; $dbi_s->finish; # # all done! if ($verbose) { print STDERR "$progname: terminating at " . localtime() . "\n"; } $dbi_h->disconnect; if (defined($reportout)) { print $out "
\n"; print $out "Report completed at " . localtime() . "\n"; print $out "\n"; print $out "\n"; close $out; rename($tmpout, $reportout) or die "$progname: rename to $reportout failed; $!"; } exit(0); OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-importstats.8.in000066400000000000000000000047241337314105200245150ustar00rootroot00000000000000.TH opendkim-importstats 8 "The Trusted Domain Project" .SH NAME .B opendkim-importstats \- OpenDKIM statistics import tool .SH SYNOPSIS .B opendkim-importstats [options] .SH DESCRIPTION .B opendkim-importstats imports collected OpenDKIM operational statistics into an SQL database. Statistics are collected by the .I opendkim(8) filter into a local file and can be output in a tabulated format by the .I opendkim-stats(8) tool. See their respective manual pages for further information. The same file is used as the input to this program, which processes it for insertion into an SQL database. The data are expected on standard input. .SH OPTIONS Long option names may be available depending on the compile-time environment for the tool. .TP .I \-d name (or \-\-dbname=name) Specifies the name of the SQL database into which records should be imported. The default is .I opendkim. .TP .I \-E Abort on certain errors, such as unknown input record types, improper field counts, etc., rather than continuing. .TP .I \-F When a malformed line is detected in the input, write the parsed data to standard error. .TP .I \-h host (or \-\-dbhost=host) Names the host to which an SQL connection should be made. The default is "localhost". .TP .I \-m Input is in the form of an email message, so do not start processing input until a blank line is encountered. .TP .I \-P port (or \-\-dbport=port) Names the port to which an SQL connection should be made. The default is determined by the scheme in use (see below). .TP .I \-p password (or \-\-dbpasswd=password) Specifies the password that should be used to authenticate to the SQL database. The default is no password. .TP .I \-r Don't automatically add unknown reporters to the database. .TP .I \-S Don't skip duplicate message records and their associated signatures. .TP .I \-s scheme (or \-\-dbscheme=scheme) Specifies the SQL scheme (backend) to be used to access the SQL database database. The default is "@SQL_BACKEND@". .TP .I \-u user (or \-\-dbuser=user) Specifies the user that should be used to authenticate to the SQL database. The default is .I opendkim. .TP .I \-v Increase verbosity of the output. .TP .I \-x Apply schema extension records. .SH VERSION This man page covers the version of .I opendkim-importstats that shipped with version @VERSION@ of .I OpenDKIM. .SH COPYRIGHT Copyright (c) 2010-2012, 2015, The Trusted Domain Project. All rights reserved. .SH SEE ALSO .I opendkim(8), .I opendkim.conf(5) .P RFC6376 - DomainKeys Identified Mail OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-importstats.c000066400000000000000000000637721337314105200241730ustar00rootroot00000000000000/* ** Copyright (c) 2010-2013, The Trusted Domain Project. All rights reserved. */ #include "build-config.h" /* system includes */ #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_GETOPT_LONG # define _GNU_SOURCE # include #endif /* HAVE_GETOPT_LONG */ /* OpenDKIM includes */ #include "stats.h" /* libbsd if found */ #ifdef USE_BSD_H # include #endif /* USE_BSD_H */ /* libstrl if needed */ #ifdef USE_STRL_H # include #endif /* USE_STRL_H */ /* libodbx includes */ #ifdef USE_ODBX # include #else /* USE_ODBX */ # error OpenDBX is required for opendkim-importstats #endif /* USE_ODBX */ /* macros, definitions */ #define CMDLINEOPTS "d:EFh:mP:p:rSs:u:vx" #define DEFDBHOST "localhost" #define DEFDBNAME "opendkim" #define DEFDBSCHEME SQL_BACKEND #define DEFDBUSER "opendkim" #define MAXLINE 2048 #define MAXREPORTER 256 /* data structures */ struct table { char * tbl_left; char * tbl_right; }; /* globals */ char *progname; char reporter[MAXREPORTER + 1]; int verbose; struct table last_insert_id[] = { { "mysql", "LAST_INSERT_ID()" }, { "sqlite3", "LAST_INSERT_ROWID()" }, { "pgsql", "LASTVAL()" }, { NULL, NULL } }; #ifdef HAVE_GETOPT_LONG /* getopt long option names */ struct option long_option[] = { { "dbhost", required_argument, NULL, 'h' }, { "dbname", required_argument, NULL, 'd' }, { "dbpasswd", required_argument, NULL, 'p' }, { "dbport", required_argument, NULL, 'P' }, { "dbscheme", required_argument, NULL, 's' }, { "dbuser", required_argument, NULL, 'u' }, { "verbose", required_argument, NULL, 'v' }, { NULL, 0, NULL, '\0' } }; #endif /* HAVE_GETOPT_LONG */ /* ** SANITIZE -- sanitize a string ** ** Parameters: ** db -- DB handle ** in -- input string ** out -- output buffer ** len -- bytes available at "out" ** ** Return value: ** 0 == string was safe ** 1 == string was not safe */ int sanitize(odbx_t *db, char *in, char *out, size_t len) { unsigned long outlen; assert(db != NULL); assert(in != NULL); assert(out != NULL); memset(out, '\0', len); outlen = len; (void) odbx_escape(db, in, strlen(in), out, &outlen); return (strncmp(in, out, (size_t) outlen) != 0); } /* ** DUMPFIELDS -- dump array of fields for debugging ** ** Parameters: ** out -- output stream ** fields -- array of fields ** n -- length of fields array ** ** Return value: ** None. */ void dumpfields(FILE *out, char **fields, int n) { int c; for (c = 0; c < n; c++) fprintf(out, "\t%d = '%s'\n", c, fields[c]); } /* ** FINDINLIST -- see if a particular string appears in another list ** ** Parameters: ** str -- string to find ** list -- colon-separated list of strings to search ** ** Return value: ** 1 -- "str" found in "list" ** 0 -- "str" not found in "list" */ int findinlist(char *str, char *list) { int len; char *p; char *q; assert(str != NULL); assert(list != NULL); len = strlen(str); q = list; for (p = list; ; p++) { if (*p == ':' || *p == '\0') { if (p - q == len && strncasecmp(str, q, len) == 0) return 1; q = p + 1; } if (*p == '\0') break; } return 0; } /* ** SQL_MKTIME -- convert a UNIX time_t (as a string) to an SQL time string ** ** Parameters: ** in -- input time ** out -- output buffer ** outlen -- bytes available at "out" ** ** Return value: ** 0 -- error ** >0 -- bytes of "out" used */ int sql_mktime(const char *in, char *out, size_t outlen) { time_t convert; struct tm *local; char *p; assert(in != NULL); assert(out != NULL); errno = 0; convert = strtoul(in, &p, 10); if (errno != 0 || *p != '\0') return 0; local = localtime(&convert); return strftime(out, outlen, "%Y-%m-%d %H:%M:%S", local); } /* ** SQL_GET_INT -- retrieve a single integer from an SQL query ** ** Parameters: ** db -- DB handle ** sql -- SQL query to perform ** ** Return value: ** -1 -- error ** 0 -- no record matched ** 1 -- extracted value */ int sql_get_int(odbx_t *db, char *sql) { int out = 0; int err; odbx_result_t *result = NULL; assert(db != NULL); assert(sql != NULL); if (verbose > 0) fprintf(stderr, "> %s\n", sql); err = odbx_query(db, sql, strlen(sql)); if (err < 0) { fprintf(stderr, "%s: odbx_query(): %s\n", progname, odbx_error(db, err)); return -1; } err = odbx_result(db, &result, NULL, 0); if (err < 0) { fprintf(stderr, "%s: odbx_result(): %s\n", progname, odbx_error(db, err)); return -1; } for (;;) { err = odbx_row_fetch(result); if (err == ODBX_ROW_DONE) { break; } else if (err < 0) { fprintf(stderr, "%s: odbx_row_fetch(): %s\n", progname, odbx_error(db, err)); return -1; } if (out == 0) { char *p; const char *op; op = odbx_field_value(result, 0); if (op == NULL) { fprintf(stderr, "%s: unexpected NULL value\n", progname); odbx_result_finish(result); return -1; } out = strtol(op, &p, 10); if (*p != '\0') { fprintf(stderr, "%s: malformed integer\n", progname); odbx_result_finish(result); return -1; } } } odbx_result_finish(result); return out; } /* ** SQL_DO -- perform an SQL operation with no result ** ** Parameters: ** db -- DB handle ** sql -- SQL action to perform ** ** Return value: ** -1 -- error ** 0 -- success */ int sql_do(odbx_t *db, char *sql) { int err; odbx_result_t *result = NULL; assert(db != NULL); assert(sql != NULL); if (verbose > 0) fprintf(stderr, "> %s\n", sql); err = odbx_query(db, sql, strlen(sql)); if (err < 0) { fprintf(stderr, "%s: odbx_query(): %s\n", progname, odbx_error(db, err)); return -1; } err = odbx_result(db, &result, NULL, 0); if (err < 0) { fprintf(stderr, "%s: odbx_result(): %s\n", progname, odbx_error(db, err)); return -1; } if (err != 2) return -1; odbx_result_finish(result); return 0; } /* ** USAGE -- print usage message and exit ** ** Parameters: ** None. ** ** Return value: ** EX_USAGE */ int usage(void) { fprintf(stderr, "%s: usage: %s [options]\n" #ifdef HAVE_GETOPT_LONG "\t-d, --dbname=name \tdatabase name (default: \"%s\")\n" "\t-E \tinput errors are fatal\n" "\t-F \tdump parsed fields on errors\n" "\t-h, --dbhost=host \tdatabase host/address (default: \"%s\")\n" "\t-m \tinput is in email format\n" "\t-P, --dbport=port \tdatabase port\n" "\t-p, --dbpasswd=passwd\tdatabase password\n" "\t-r \tdon't add unknown reporters\n" "\t-S \tdon't skip duplicate messages\n" "\t-s, --dbscheme=scheme\tdatabase scheme (default: \"%s\")\n" "\t-u, --dbuser=user \tdatabase user (default: \"%s\")\n" "\t-v, --verbose \tincrease verbose output\n" # ifdef _FFR_STATSEXT "\t-x \timport extension records\n" # endif /* _FFR_STATSEXT */ #else /* HAVE_GETOPT_LONG */ "\t-d name \tdatabase name (default: \"%s\")\n" "\t-E \tinput errors are fatal\n" "\t-F \tdump parsed fields on errors\n" "\t-h host \tdatabase host/address (default: \"%s\")\n" "\t-m \tinput is in email format\n" "\t-P port \tdatabase port\n" "\t-p passwd\tdatabase password\n" "\t-r \tdon't add unknown reporters\n" "\t-S \tdon't skip duplicate messages\n" "\t-s scheme\tdatabase scheme (default: \"%s\")\n" "\t-u user \tdatabase user (default: \"%s\")\n" "\t-v \tincrease verbose output\n" # ifdef _FFR_STATSEXT "\t-x \timport extension records\n" # endif /* _FFR_STATSEXT */ #endif /* HAVE_GETOPT_LONG */ , progname, progname, DEFDBNAME, DEFDBHOST, DEFDBSCHEME, DEFDBUSER); return EX_USAGE; } /* ** MAIN -- program mainline ** ** Parameters: ** argc, argv -- the usual ** ** Return value: ** Exit status. */ int main(int argc, char **argv) { int c; int n; #ifdef _FFR_STATSEXT int extensions = 0; #endif /* _FFR_STATSEXT */ int nfields = 0; int line; int err; int mail = 0; int dontskip = 0; int fatalerrors = 0; int showfields = 0; int skipsigs = 0; int norepadd = 0; int repid; int domid; int addrid; int msgid; int sigid; int inversion = -1; #ifdef HAVE_GETOPT_LONG int long_opt_index = 0; #endif /* HAVE_GETOPT_LONG */ char *p; char *lastrow = NULL; char *dbhost = DEFDBHOST; char *dbname = DEFDBNAME; char *dbscheme = DEFDBSCHEME; char *dbuser = DEFDBUSER; char *dbpassword = NULL; char *dbport = NULL; char **fields = NULL; odbx_t *db = NULL; char buf[MAXLINE + 1]; char timebuf[MAXLINE + 1]; char sql[MAXLINE + 1]; char safesql[MAXLINE * 2 + 1]; progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; verbose = 0; #ifdef HAVE_GETOPT_LONG while ((c = getopt_long(argc, argv, CMDLINEOPTS, long_option, &long_opt_index)) != -1) #else /* HAVE_GETOPT_LONG */ while ((c = getopt(argc, argv, CMDLINEOPTS)) != -1) #endif /* HAVE_GETOPT_LONG */ { switch (c) { case 'd': dbname = optarg; break; case 'E': fatalerrors = 1; break; case 'F': showfields = 1; break; case 'h': dbhost = optarg; break; case 'm': mail = 1; break; case 'P': dbport = optarg; break; case 'p': dbpassword = optarg; break; case 'r': norepadd = 1; break; case 'S': dontskip = 1; break; case 's': dbscheme = optarg; break; case 'u': dbuser = optarg; break; case 'v': verbose++; break; #ifdef _FFR_STATSEXT case 'x': extensions = 1; break; #endif /* _FFR_STATSEXT */ default: return usage(); } } for (c = 0; ; c++) { if (strcasecmp(last_insert_id[c].tbl_left, dbscheme) == 0) { lastrow = last_insert_id[c].tbl_right; break; } } if (lastrow == NULL) { fprintf(stderr, "%s: scheme \"%s\" not currently supported\n", progname, dbscheme); return EX_SOFTWARE; } /* try to connect to the database */ if (odbx_init(&db, dbscheme, dbhost, dbport) < 0) { fprintf(stderr, "%s: odbx_init() failed\n", progname); return EX_TEMPFAIL; } /* bind with user, password, database information */ err = odbx_bind(db, dbname, dbuser, dbpassword, ODBX_BIND_SIMPLE); if (err < 0) { fprintf(stderr, "%s: odbx_bind(): %s\n", progname, odbx_error(db, err)); (void) odbx_finish(db); return EX_TEMPFAIL; } /* initialize stuff */ memset(buf, '\0', sizeof buf); memset(reporter, '\0', sizeof reporter); line = 0; repid = 0; msgid = 0; sigid = 0; /* read lines from stdin */ while (fgets(buf, sizeof buf - 1, stdin) != NULL) { line++; /* eat the newline */ for (p = buf; *p != '\0'; p++) { if (*p == '\n') { *p = '\0'; break; } } if (mail == 1) { if (strlen(buf) > 0) continue; mail = 0; continue; } /* first byte identifies the record type */ c = buf[0]; /* reset fields array */ if (fields != NULL) memset(fields, '\0', sizeof(char *) * nfields); /* now break out the fields */ n = 0; for (p = strtok(buf + 1, "\t"); p != NULL; p = strtok(NULL, "\t")) { if (nfields == n) { int newnf; size_t newsz; char **new; newnf = MAX(nfields * 2, 8); newsz = sizeof(char *) * newnf; if (nfields == 0) new = (char **) malloc(newsz); else new = (char **) realloc(fields, newsz); if (new == NULL) { fprintf(stderr, "%s: %salloc(): %s\n", progname, fields == NULL ? "m" : "re", strerror(errno)); (void) odbx_finish(db); return EX_SOFTWARE; } nfields = newnf; fields = new; } fields[n++] = p; } sigid = 0; /* processing section for messages */ if (c == '\0') { continue; } else if (c == 'V') { if (n != 1) { fprintf(stderr, "%s: unexpected version field count (%d) at input line %d\n", progname, n, line); if (showfields == 1) dumpfields(stderr, fields, n); if (fatalerrors == 1) { (void) odbx_finish(db); return EX_DATAERR; } continue; } inversion = atoi(fields[0]); } else if (c == 'M') { if (inversion != DKIMS_VERSION) { fprintf(stderr, "%s: ignoring old format at input line %d\n", progname, line); continue; } if (n != DKIMS_MI_MAX + 1) { fprintf(stderr, "%s: unexpected message field count (%d) at input line %d\n", progname, n, line); if (showfields == 1) dumpfields(stderr, fields, n); if (fatalerrors == 1) { (void) odbx_finish(db); return EX_DATAERR; } continue; } skipsigs = 0; /* get, or create, the reporter ID if needed */ if (strcasecmp(reporter, fields[1]) != 0) { (void) sanitize(db, fields[1], safesql, sizeof safesql); snprintf(sql, sizeof sql, "SELECT id FROM reporters WHERE name = '%s'", safesql); repid = sql_get_int(db, sql); if (repid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (repid == 0) { if (norepadd == 1) { fprintf(stderr, "%s: no such reporter '%s' at line %d\n", progname, fields[1], line); skipsigs = 1; continue; } snprintf(sql, sizeof sql, "INSERT INTO reporters (name) VALUES ('%s')", safesql); repid = sql_do(db, sql); if (repid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } snprintf(sql, sizeof sql, "SELECT %s", lastrow); repid = sql_get_int(db, sql); if (repid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (repid == 0) { fprintf(stderr, "%s: failed to create reporter record for '%s'\n", progname, fields[1]); (void) odbx_finish(db); return EX_SOFTWARE; } } strlcpy(reporter, fields[1], sizeof reporter); } /* get, or create, the domain ID if needed */ (void) sanitize(db, fields[2], safesql, sizeof safesql); snprintf(sql, sizeof sql, "SELECT id FROM domains WHERE name = '%s'", safesql); domid = sql_get_int(db, sql); if (domid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (domid == 0) { snprintf(sql, sizeof sql, "INSERT INTO domains (name) VALUES ('%s')", safesql); domid = sql_do(db, sql); if (domid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } snprintf(sql, sizeof sql, "SELECT %s", lastrow); domid = sql_get_int(db, sql); if (domid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (domid == 0) { fprintf(stderr, "%s: failed to create domain record for '%s'\n", progname, fields[2]); (void) odbx_finish(db); return EX_SOFTWARE; } } /* get, or create, the IP address ID if needed */ (void) sanitize(db, fields[3], safesql, sizeof safesql); snprintf(sql, sizeof sql, "SELECT id FROM ipaddrs WHERE addr = '%s'", safesql); addrid = sql_get_int(db, sql); if (addrid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (addrid == 0) { snprintf(sql, sizeof sql, "INSERT INTO ipaddrs (addr) VALUES ('%s')", safesql); addrid = sql_do(db, sql); if (addrid == -1) { /* repeat the get */ snprintf(sql, sizeof sql, "SELECT id FROM ipaddrs WHERE addr = '%s'", safesql); addrid = sql_get_int(db, sql); if (addrid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } } else { snprintf(sql, sizeof sql, "SELECT %s", lastrow); addrid = sql_get_int(db, sql); if (addrid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (addrid == 0) { fprintf(stderr, "%s: failed to create IP address record for '%s'\n", progname, fields[3]); (void) odbx_finish(db); return EX_SOFTWARE; } } } /* verify data safety */ if (sanitize(db, fields[0], safesql, sizeof safesql) || sanitize(db, fields[4], safesql, sizeof safesql) || sanitize(db, fields[5], safesql, sizeof safesql) || sanitize(db, fields[6], safesql, sizeof safesql) || sanitize(db, fields[7], safesql, sizeof safesql) || sanitize(db, fields[8], safesql, sizeof safesql)) { fprintf(stderr, "%s: unsafe data at input line %d\n", progname, line); skipsigs = 1; continue; } /* see if this is a duplicate */ (void) sql_mktime(fields[4], timebuf, sizeof timebuf); snprintf(sql, sizeof sql, "SELECT id FROM messages WHERE jobid = '%s' AND reporter = %d AND msgtime = '%s'", fields[0], repid, timebuf); msgid = sql_get_int(db, sql); if (msgid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (msgid != 0) { if (dontskip == 0) { fprintf(stderr, "%s: skipping duplicate message at line %d\n", progname, line); skipsigs = 1; } continue; } (void) sql_mktime(fields[4], timebuf, sizeof timebuf); snprintf(sql, sizeof sql, "INSERT INTO messages (jobid, reporter, from_domain, ip, msgtime, size, sigcount, atps, spam) VALUES ('%s', %d, %d, %d, '%s', %s, %s, %s, %s)", fields[0], /* jobid */ repid, /* reporter */ domid, /* from_domain */ addrid, /* ip */ timebuf, /* msgtime */ fields[5], /* size */ fields[6], /* sigcount */ fields[7], /* atps */ fields[8]); /* spam */ msgid = sql_do(db, sql); if (msgid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } /* get back the message ID */ snprintf(sql, sizeof sql, "SELECT %s", lastrow); msgid = sql_get_int(db, sql); if (msgid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (msgid == 0) { fprintf(stderr, "%s: failed to create message record for '%s'\n", progname, fields[0]); (void) odbx_finish(db); return EX_SOFTWARE; } } /* processing section for signatures */ else if (c == 'S') { if (inversion != DKIMS_VERSION) { fprintf(stderr, "%s: ignoring old format at input line %d\n", progname, line); continue; } if (n != DKIMS_SI_MAX + 1) { fprintf(stderr, "%s: unexpected signature field count (%d) at input line %d\n", progname, n, line); continue; } else if (msgid <= 0) { fprintf(stderr, "%s: signature record before message record at input line %d\n", progname, line); continue; } else if (skipsigs == 1) { continue; } /* get, or create, the domain ID if needed */ (void) sanitize(db, fields[0], safesql, sizeof safesql); snprintf(sql, sizeof sql, "SELECT id FROM domains WHERE name = '%s'", safesql); domid = sql_get_int(db, sql); if (domid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (domid == 0) { snprintf(sql, sizeof sql, "INSERT INTO domains (name) VALUES ('%s')", safesql); domid = sql_do(db, sql); if (domid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } snprintf(sql, sizeof sql, "SELECT %s", lastrow); domid = sql_get_int(db, sql); if (domid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (domid == 0) { fprintf(stderr, "%s: failed to create domain record for '%s'\n", progname, fields[0]); (void) odbx_finish(db); return EX_SOFTWARE; } } if (sanitize(db, fields[1], safesql, sizeof safesql) || sanitize(db, fields[2], safesql, sizeof safesql) || sanitize(db, fields[3], safesql, sizeof safesql) || sanitize(db, fields[4], safesql, sizeof safesql) || sanitize(db, fields[5], safesql, sizeof safesql)) { fprintf(stderr, "%s: unsafe data at input line %d\n", progname, line); continue; } snprintf(sql, sizeof sql, "INSERT INTO signatures (message, domain, pass, fail_body, siglength, sigerror, dnssec) VALUES (%d, %d, %s, %s, %s, %s, %s)", msgid, /* message */ domid, /* domain */ fields[1], /* pass */ fields[2], /* fail_body */ fields[3], /* siglength */ fields[4], /* sigerror */ fields[5]); /* dnssec */ sigid = sql_do(db, sql); if (sigid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } /* get back the signature ID */ snprintf(sql, sizeof sql, "SELECT %s", lastrow); sigid = sql_get_int(db, sql); if (sigid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (sigid == 0) { fprintf(stderr, "%s: failed to create signature record for input line %d\n", progname, line); (void) odbx_finish(db); return EX_SOFTWARE; } } /* processing section for message status updates */ else if (c == 'U' && inversion == DKIMS_VERSION) { if (n != 4) { fprintf(stderr, "%s: unexpected update field count (%d) at input line %d\n", progname, n, line); if (showfields == 1) dumpfields(stderr, fields, n); continue; } /* get the reporter ID */ if (strcasecmp(reporter, fields[1]) != 0) { (void) sanitize(db, fields[1], safesql, sizeof safesql); snprintf(sql, sizeof sql, "SELECT id FROM reporters WHERE name = '%s'", safesql); repid = sql_get_int(db, sql); if (repid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (repid == 0) { if (norepadd == 1) { fprintf(stderr, "%s: no such reporter '%s' at line %d\n", progname, fields[1], line); } continue; } strlcpy(reporter, fields[1], sizeof reporter); } /* verify data safety */ if (sanitize(db, fields[0], safesql, sizeof safesql) || sanitize(db, fields[2], safesql, sizeof safesql) || sanitize(db, fields[3], safesql, sizeof safesql)) { fprintf(stderr, "%s: unsafe data at input line %d\n", progname, line); continue; } /* get the message ID */ if (strcmp(fields[2], "0") == 0) { snprintf(sql, sizeof sql, "SELECT MAX(id) FROM messages WHERE jobid = '%s' AND reporter = %d", fields[0], repid); } else { (void) sql_mktime(fields[2], timebuf, sizeof timebuf); snprintf(sql, sizeof sql, "SELECT id FROM messages WHERE jobid = '%s' AND reporter = %d AND msgtime = '%s'", fields[0], repid, timebuf); } msgid = sql_get_int(db, sql); if (msgid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } else if (msgid == 0) { fprintf(stderr, "%s: unknown message for update at line %d\n", progname, line); continue; } snprintf(sql, sizeof sql, "UPDATE messages SET spam = %s WHERE id = %d", fields[3], /* spam */ msgid); /* message ID */ msgid = sql_do(db, sql); if (msgid == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } } #ifdef _FFR_STATSEXT /* processing section for extensions */ else if (c == 'X') { if (inversion != DKIMS_VERSION) { fprintf(stderr, "%s: ignoring old format at input line %d\n", progname, line); continue; } if (n != 2) { fprintf(stderr, "%s: unexpected extension field count (%d) at input line %d\n", progname, n, line); if (showfields == 1) dumpfields(stderr, fields, n); continue; } else if (msgid <= 0) { fprintf(stderr, "%s: extension record before message record at input line %d\n", progname, line); continue; } else if (skipsigs == 1 || extensions == 0) { continue; } if (sanitize(db, fields[0], safesql, sizeof safesql) || sanitize(db, fields[1], safesql, sizeof safesql)) { fprintf(stderr, "%s: unsafe data at input line %d\n", progname, line); continue; } snprintf(sql, sizeof sql, "UPDATE messages SET %s = %s WHERE id = %d", fields[0], fields[1], msgid); err = sql_do(db, sql); if (err == -1) { (void) odbx_finish(db); return EX_SOFTWARE; } } #endif /* _FFR_STATSEXT */ /* unknown record type */ else { fprintf(stderr, "%s: unknown record type '%c' at input line %d\n", progname, c, line); if (fatalerrors == 1) { (void) odbx_finish(db); return EX_DATAERR; } } } if (fields != NULL) free(fields); if (ferror(stdin)) { fprintf(stderr, "%s: fgets(): %s\n", progname, strerror(errno)); (void) odbx_finish(db); return EX_OSERR; } /* unbind */ err = odbx_unbind(db); if (err < 0) { fprintf(stderr, "%s: odbx_unbind(): %s\n", progname, odbx_error(db, err)); (void) odbx_finish(db); return EX_SOFTWARE; } /* shut down */ if (odbx_finish(db) < 0) { fprintf(stderr, "%s: odbx_finish() failed\n", progname); return EX_SOFTWARE; } return EX_OK; } OpenDKIM-rel-opendkim-2-11-0-Beta2/stats/opendkim-reportstats.in000066400000000000000000000342451337314105200243510ustar00rootroot00000000000000#!/bin/sh # # Copyright (c) 2012, The Trusted Domain Project. All rights reserved. # # Script to upload OpenDKIM statistics data. Original contributed # by John Wood. # # ## ## opendkim(8) configuration file location ## OPENDKIMCONFIG="/etc/mail/opendkim.conf" ## ## Owner and group of the statistics file ## (Leave empty to skip the re-creation step and let opendkim(8) do it) ## OPENDKIMDATOWNER="mailnull:mailnull" ## =========================================== ## NO USER SERVICEABLE PARTS BEYOND THIS POINT ## =========================================== PROGNAME=`basename $0` OPENDKIMSTATS=`awk '$1 == "Statistics" { print $2 }' $OPENDKIMCONFIG` if [ x"$OPENDKIMSTATS" = x"" ] then echo "${PROGNAME}: can't determine statistics file location from ${OPENDKIMCONFIG}" exit 1 fi OPENDKIMSTATSDIR=`dirname $OPENDKIMSTATS` OPENDKIMSTATSFILE=`basename $OPENDKIMSTATS` REPORTERNAME="OpenDKIM Filter User" REPORTEREMAIL="<`whoami`@$HOSTNAME>" UNIXDATE=`date +%s` HOSTNAME=`hostname` OPENDKIMSTATSDAT="${OPENDKIMSTATSDIR}/${OPENDKIMSTATSFILE}" REPORTSTUB="${OPENDKIMSTATSDIR}/report_stub.txt" GNUPGDIR="${OPENDKIMSTATSDIR}/.gnupg" STATEMAIL="OpenDKIM Statistics Reporting Key " STATEMAILSIMPLE="stats-report@opendkim.org" REGISTEREMAIL="OpenDKIM Stats Registration " SENDMAILFLAGS="-t -f $REPORTEREMAIL" ODKGNUPGURL="http://www.opendkim.org/stats/stats_opendkim_org.pub" ODKGNUPGMD5URL="http://www.opendkim.org/stats/stats_opendkim_org.pub.md5" ODKGNUPGCERT="${GNUPGDIR}/opendkim_org.pem" ODKGNUPGMD5="${GNUPGDIR}/stats_opendkim_org.pub.md5" OPENDKIMSTATS="@VERSION@" # # VERSION -- output version string # version() { echo "${PROGNAME} v{OPENDKIMSTATS}" exit 0 } # # USAGE -- output usage message # usage() { echo "${PROGNAME}: usage: ${PROGNAME} " echo echo "Valid modes:" echo echo " -register Downloads the opendkim.org public key," echo " generates stats reporting GPG setup, and" echo " sends a registration request" echo echo " -sendregistration Sends pre-setup GPG registration to" ecoh " opendkim.org in case initial registration" echo " has problems sending email" echo echo " -sendstats Sends latest OpenDKIM stats to opendkim.org" echo echo " -version Displays the version and exits" exit 0 } # # SET_PATHS -- set PATH and SENDMAIL variables # set_paths() { # Try to ensure proper execution by adding likely paths PATH=$PATH:/usr/sbin:/sbin:/usr/bin:/usr/lib for i in /usr/local/bin /usr/local/sbin /opt/local/bin \ /opt/local/sbin /usr/sfw/bin /usr/sfw/sbin do if [ -d "$i" ]; then PATH=$PATH:$i export PATH fi done # Solaris if [ -f '/usr/lib/sendmail' ] then SENDMAIL="/usr/lib/sendmail" else SENDMAIL="/usr/sbin/sendmail" fi } # # CHECK_OPENSSL -- try to find the openssl binary # check_openssl() { OPENSSL=`which openssl` if [ -z "$OPENSSL" ]; then echo "${PROGNAME}: cannot locate openssl binary" exit 1 fi } # # CHECK_GPG -- try to find the gpg binary # check_gpg() { GPG=`which gpg` if [ -z "$GPG" ]; then echo "${PROGNAME}: cannot locate gpg binary" exit 1 fi } # # CHECK_GPG_SETUP -- verify the OpenDKIM public key is in the local keyring # check_gpg_setup() { GPGVERIFY=`gpg --homedir="$GNUPGDIR" --no-permission-warning --list-keys | \ grep "$STATEMAIL" | \ awk -FO '{print "O"$2}'` if [ "$GPGVERIFY" != "$STATEMAIL" ] then echo "${PROGNAME}: could not verify imported GPG key for $STATEMAIL" echo "${PROGNAME}: run \"${PROGNAME} -register\" first" exit 1 fi GPGSETUP=`gpg --homedir="$GNUPGDIR" --no-permission-warning --list-keys | \ grep -v "$STATEMAIL" | \ grep "OpenDKIM"` if [ -z "$GPGSETUP" ] then echo "${PROGNAME}: GPG setup incomplete" echo "${PROGNAME}: run \"${PROGNAME}\" again" exit 1 fi } # # CHECK_WEB_APP -- figure out what web "GET" application is available # check_web_app() { WGET=`which wget` if [ ! -z "$WGET" ] then WEBAPP=wget elif [ -z "$WGET" ] then CURL=`which curl` if [ -z "$CURL" ] then echo "${PROGNAME}: cannot locate wget or curl" exit 1 fi WEBAPP=curl fi } # # GET_OPENDKIM_ORG_PUB_CERT -- go get the OpenDKIM public key for signing # get_opendkim_org_pub_cert() { # safety net if [ $? != 0 ] then echo "${PROGNAME}: cannot locate wget or curl" exit 1 fi # get the md5 sum file first if [ x"$WEBAPP" = x"wget" ] then "$WEBAPP" -q -c --tries=10 -T 340 \ -O "$ODKGNUPGMD5" "$ODKGNUPGMD5URL" elif [ "$WEBAPP" = curl ] then "$WEBAPP" -s -m 340 "$ODKGNUPGMD5URL" > "$ODKGNUPGMD5" fi if [ $? != 0 ] then echo "${PROGNAME}: failed to retrieve ${ODKGNUPGMD5URL}" exit 1 fi # get the public cert if [ "$WEBAPP" = wget ] then "$WEBAPP" -q -c --tries=10 -T 340 \ -O "$ODKGNUPGCERT" "$ODKGNUPGURL" elif [ "$WEBAPP" = curl ] then "$WEBAPP" -s -m 340 "$ODKGNUPGURL" > "$ODKGNUPGCERT" fi if [ $? != 0 ] then echo "${PROGNAME}: failed to retrieve ${ODKGNUPGURL}" exit 1 fi # verify the md5 sum of the public cert if [ -f "$ODKGNUPGMD5" ] && [ -f "$ODKGNUPGCERT" ] then ODKORGSUM=`cat "$ODKGNUPGMD5"` LOCALSUM=`"$OPENSSL" md5 "$ODKGNUPGCERT" | awk '{print $2}'` else echo "${PROGNAME}: $ODKGNUPGMD5 or ${ODKGNUPGCERT} absent/unreadable" exit 1 fi if [ "$ODKORGSUM" != "$LOCALSUM" ] then echo "${PROGNAME}: MD5 checksum for $ODKGNUPGCERT failed" echo "${PROGNAME}: (expecting ${ODKORGSUM}, got ${LOCALSUM})" exit 1 fi } # # INPUT_CONTACT_INFO -- prompt for details we want to store in the key # input_contact_info() { NAMEVALID=0 INPUTNAME="" EMAILVALID=0 INPUTEMAIL="" NAMELENGTH=0 CONTACTEMAIL="" until [ "$NAMEVALID" = 1 ] do printf "Please enter your name: " read INPUTNAME NAMELENGTH=`echo "$INPUTNAME" | wc -c` if [ "$NAMELENGTH" -lt 5 ] then INPUTNAME="" echo "${PROGNAME}: name must be at least five characters long" fi if [ ! -z "$INPUTNAME" ] then NAMEVALID=1 fi done until [ "$EMAILVALID" = 1 ] do printf "Please enter your contact email for OpenDKIM stats: " read INPUTEMAIL CONTACTEMAIL=`echo $INPUTEMAIL | egrep '[^[:space:]]+\>@[a-zA-Z0-9_\.]+\.[a-zA-Z]{2,3}'` if [ ! -z "$CONTACTEMAIL" ] then EMAILVALID=1 else echo "${PROGNAME}: invalid email address syntax" fi done } # # OPENDKIM_GPG_IMPORT -- set up GPG and import the OpenDKIM key # opendkim_gpg_import() { echo "${PROGNAME}: retrieving opendkim.org public GPG certificate" get_opendkim_org_pub_cert if [ $? != 0 ] then echo "${PROGNAME}: failed to retrieve opendkim.org public GPG certificate" exit 1 fi echo "${PROGNAME}: importing opendkim.org public GPG certificate" if [ ! -d "$GNUPGDIR" ] then echo "${PROGNAME}: directory ${GNUPGDIR} missing" exit 1 fi cat > "${GNUPGDIR}/gpg.conf" < is correct? [y/n]: " read AGREE done if [ -z "$INPUTNAME" ] || [ -z "$INPUTEMAIL" ] then echo "${PROGNAME}: missing contact information, cannot generate GPG certificates" echo "${PROGNAME}: run \"${PROGNAME} -register\"" exit 1 fi # Generate the key INPUTFILE="${GNUPGDIR}/${UNIXDATE}.temp.gpg" echo "# input file to generate GnuPG keys automatically" > $INPUTFILE echo >> $INPUTFILE echo "%echo Generating a standard key" >> $INPUTFILE echo >> $INPUTFILE echo "#######################################" >> $INPUTFILE echo "# parameters for the key" >> $INPUTFILE echo >> $INPUTFILE echo "Key-Type: DSA" >> $INPUTFILE echo "Key-Length: 1024" >> $INPUTFILE echo "Subkey-Type: ELG-E" >> $INPUTFILE echo "Subkey-Length: 2048" >> $INPUTFILE echo >> $INPUTFILE echo "Name-Real: $INPUTNAME" >> $INPUTFILE echo "Name-Comment: OpenDKIM GnuPG key" >> $INPUTFILE echo "Name-Email: $INPUTEMAIL" >> $INPUTFILE echo >> $INPUTFILE echo "Expire-Date: 0" >> $INPUTFILE echo >> $INPUTFILE echo "######################################" >> $INPUTFILE echo >> $INPUTFILE echo "# the keyring files" >> $INPUTFILE echo "%pubring ${GNUPGDIR}/pubring.gpg" >> $INPUTFILE echo "%secring ${GNUPGDIR}/secring.gpg" >> $INPUTFILE echo >> $INPUTFILE echo "# perform key generation" >> $INPUTFILE echo "%commit" >> $INPUTFILE echo >> $INPUTFILE echo "%echo done" >> $INPUTFILE echo "#EOF" >> $INPUTFILE echo >> $INPUTFILE if [ ! -f "$INPUTFILE" ] then echo "${PROGNAME}: failed to create temporary file for GPG key generation" exit 1 fi # call GPG on the temp file echo "${PROGNAME}: generating signing key" gpg --batch --gen-key --homedir="$GNUPGDIR" \ --keyring="${GNUPGDIR}/pubring.gpg" \ --secret-keyring="${GNUPGDIR}/secring.gpg" "$INPUTFILE" if [ $? != 0 ] then echo "${PROGNAME}: signing key generation failed" exit 1 fi rm "$INPUTFILE" } # # NAME_FROM_KEY -- try to get name/email from gnupg key # name_from_key() { REPORTER=`gpg --homedir="$GNUPGDIR" --list-keys | grep 'OpenDKIM GnuPG key' | sed 's/^uid *//'` if [ ! -z "$REPORTER" ] then REPORTERNAME=`echo $REPORTER | awk -F\< '{print $1}'` REPORTEREMAIL=`echo $REPORTER | awk -F\< '{print "<"$2}'` if [ -z "$REPORTERNAME" ] || [ -z "$REPORTEREMAIL" ] then REPORTERNAME="OpenDKIM Filter User" REPORTEREMAIL="<`whoami`@$HOSTNAME>" fi fi # re-eval flags to set the envelope as well SENDMAILFLAGS="-t -f $REPORTEREMAIL" } # # SEND_REGISTRATION -- send registration # send_registration() { echo "${PROGNAME}: preparing signing key submission" gpg --batch -a --export --homedir="$GNUPGDIR" \ --out="/tmp/$HOSTNAME.public.key" if [ $? != 0 ] then echo "${PROGNAME}: unable to export public key" exit 1 fi if [ -f /tmp/$HOSTNAME.public.key ] then mv /tmp/$HOSTNAME.public.key "${GNUPGDIR}"/ fi # encrypt public key and prep for sending to OpenDKIM gpg -a --homedir="$GNUPGDIR" -o \ "${GNUPGDIR}/${HOSTNAME}.${UNIXDATE}.gpg" -e \ -r "$STATEMAILSIMPLE" -- "${GNUPGDIR}/${HOSTNAME}.public.key" 2>/dev/null if [ ! -f "${GNUPGDIR}/${HOSTNAME}.${UNIXDATE}.gpg" ] then echo "${PROGNAME}: encrypted key generation failed" rm /tmp/"{$HOSTNAME}".public.key exit 1 fi name_from_key # create a one time stub echo "From: ${REPORTERNAME} ${REPORTEREMAIL}" > $REPORTSTUB echo "To: ${REGISTEREMAIL}" >> $REPORTSTUB echo "Subject: OpenDKIM stats reporting registration from ${REPORTEREMAIL}" >> $REPORTSTUB # send registration email cat $REPORTSTUB ${GNUPGDIR}/${HOSTNAME}.${UNIXDATE}.gpg | \ ${SENDMAIL} ${SENDMAILFLAGS} if [ $? != 0 ] then echo "${PROGNAME}: unable to send registration email" exit 1 fi echo "${PROGNAME}: registration submitted to OpenDKIM" rm ${GNUPGDIR}/${HOSTNAME}.${UNIXDATE}.gpg rm ${GNUPGDIR}/${HOSTNAME}.public.key rm ${REPORTSTUB} } # # SEND_STATS -- send the current stats batch # send_stats() { if [ ! -s "$OPENDKIMSTATSDAT" ] then echo "{$PROGNAME}: ${OPENDKIMSTATSDAT} empty or missing" exit 1 fi GPGVERIFY=`gpg --homedir="$GNUPGDIR" --no-permission-warning --list-keys | \ grep "$STATEMAIL" | awk -FO '{print "O"$2}'` if [ "$GPGVERIFY" != "$STATEMAIL" ] then echo "${PROGNAME}: could not verify imported GPG key for: ${STATEMAIL}" echo "${PROGNAME}: run \"${PROGNAME} -register\"" exit 1 fi name_from_key echo "From: ${REPORTERNAME} ${REPORTEREMAIL}" > $REPORTSTUB echo "To: $STATEMAIL" >> $REPORTSTUB echo "Subject: opendkim-stats report from ${HOSTNAME} at ${UNIXDATE}" >> $REPORTSTUB if [ ! -s "$REPORTSTUB" ] then echo "${PROGNAME}: report stub empty or missing" exit 1 fi # clearsign statistics data gpg --homedir="$GNUPGDIR" \ --output "${GNUPGDIR}/${OPENDKIMSTATSFILE}.${HOSTNAME}.${UNIXDATE}.gpg" \ --clearsign $OPENDKIMSTATSDAT if [ $? != 0 ] then echo "${PROGNAME}: GPG clearsign of stats file ${OPENDKIMSTATSDAT} failed" rm $REPORTSTUB exit 1 fi if [ ! -f "${GNUPGDIR}/${OPENDKIMSTATSFILE}.${HOSTNAME}.${UNIXDATE}.gpg" ] then echo "${PROGNAME}: GPG clearsign of stats file ${OPENDKIMSTATSDAT} missing" rm $REPORTSTUB exit 1 fi cat $REPORTSTUB ${GNUPGDIR}/${OPENDKIMSTATSFILE}.${HOSTNAME}.${UNIXDATE}.gpg | \ ${SENDMAIL} ${SENDMAILFLAGS} if [ $? != 0 ] then echo "${PROGNAME}: sending of ${GNUPGDIR}/${OPENDKIMSTATSFILE}.${HOSTNAME}.${UNIXDATE}.gpg failed" exit 1 fi rm ${GNUPGDIR}/${OPENDKIMSTATSFILE}.${HOSTNAME}.${UNIXDATE}.gpg # change this to cp when testing mv $OPENDKIMSTATSDAT ${OPENDKIMSTATSDAT}.old if [ ! -z "$OPENDKIMDATOWNER" ] then touch $OPENDKIMSTATSDAT touch ${OPENDKIMSTATSDIR}/last_report chown $OPENDKIMDATOWNER $OPENDKIMSTATSDAT chmod 0660 $OPENDKIMSTATSDAT fi rm -f $REPORTSTUB echo "${PROGNAME}: OpenDKIM stats sent at `date`" exit 0 } case "$1" in -register) set_paths check_openssl check_gpg check_web_app register opendkim_gpg_import send_registration ;; -sendregistration) set_paths check_openssl check_gpg check_gpg_setup send_registration ;; -sendstats) set_paths check_openssl check_gpg send_stats ;; -version) version ;; *) usage esac