├── .gitignore ├── KNOWNBUGS ├── LICENSE ├── LICENSE.Sendmail ├── Makefile.am ├── README ├── RELEASE_NOTES ├── configure.ac ├── contrib ├── Makefile.am ├── docs │ ├── Makefile.am │ ├── draft-andersen-arc-05.txt │ └── draft-andersen-arc.xml ├── init │ ├── Makefile.am │ ├── generic │ │ ├── Makefile.am │ │ ├── README │ │ └── openarc │ ├── redhat │ │ ├── .gitignore │ │ ├── Makefile.am │ │ └── openarc.in │ └── solaris │ │ ├── Makefile.am │ │ ├── openarc │ │ └── openarc.xml ├── spec │ ├── .gitignore │ ├── Makefile.am │ └── openarc.spec.in └── systemd │ ├── .gitignore │ ├── Makefile.am │ └── openarc.service.in ├── copyright-check ├── docs └── Makefile.am ├── libopenarc ├── .gitignore ├── Makefile.am ├── arc-canon.c ├── arc-canon.h ├── arc-dns.c ├── arc-dns.h ├── arc-internal.h ├── arc-keys.c ├── arc-keys.h ├── arc-tables.c ├── arc-tables.h ├── arc-types.h ├── arc-util.c ├── arc-util.h ├── arc.c ├── arc.h ├── base64.c ├── base64.h ├── docs │ ├── Makefile.am │ └── index.html ├── openarc.pc.in └── tests │ └── Makefile.am ├── m4 ├── .gitignore └── ac_pthread.m4 └── openarc ├── .gitignore ├── Makefile.am ├── config.c ├── config.h ├── openarc-ar.c ├── openarc-ar.h ├── openarc-config.h ├── openarc-crypto.c ├── openarc-crypto.h ├── openarc-test.c ├── openarc-test.h ├── openarc.8.in ├── openarc.c ├── openarc.conf.5.in ├── openarc.conf.sample ├── openarc.conf.simple.in ├── openarc.h ├── tests └── Makefile.am ├── util.c └── util.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | 34 | # tarballs 35 | *.tar.gz 36 | 37 | # other nonsense 38 | aclocal.m4 39 | autom4te.cache 40 | build-aux 41 | build-config.h 42 | build-config.h.in 43 | configure 44 | libtool 45 | Makefile 46 | Makefile.in 47 | CONFIG 48 | config.log 49 | config.status 50 | stamp-h1 51 | .deps/* 52 | *~ 53 | *.cache 54 | *#* 55 | 56 | # compilation artifacts 57 | libopenarc/symbols.map 58 | openarc/.libs/ 59 | -------------------------------------------------------------------------------- /KNOWNBUGS: -------------------------------------------------------------------------------- 1 | 2 | 3 | K N O W N B U G S I N O P E N A R C 4 | 5 | 6 | The following are bugs or deficiencies in the OpenARC package that we 7 | are aware of but which have not been fixed in the current release. You 8 | probably want to get the most up to date version of this from 9 | http://www.trusteddomain.org. For descriptions of bugs that 10 | have been fixed, see the file RELEASE_NOTES. 11 | 12 | This list is not guaranteed to be complete. Check the Trusted Domain Project 13 | web site for additional pending bugs and feature requests. 14 | 15 | [TBD] 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Murray S. Kucherawy 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /LICENSE.Sendmail: -------------------------------------------------------------------------------- 1 | SENDMAIL OPEN SOURCE LICENSE 2 | 3 | The following license terms and conditions apply to this open source 4 | software ("Software"), unless a different license is obtained directly 5 | from Sendmail, Inc. ("Sendmail") located at 6475 Christie Ave, Suite 350, 6 | Emeryville, CA 94608, USA. 7 | 8 | Use, modification and redistribution (including distribution of any 9 | modified or derived work) of the Software in source and binary forms is 10 | permitted only if each of the following conditions of 1-6 are met: 11 | 12 | 1. Redistributions of the Software qualify as "freeware" or "open 13 | source software" under one of the following terms: 14 | 15 | (a) Redistributions are made at no charge beyond the reasonable 16 | cost of materials and delivery; or 17 | 18 | (b) Redistributions are accompanied by a copy of the modified 19 | Source Code (on an acceptable machine-readable medium) or by an 20 | irrevocable offer to provide a copy of the modified Source Code 21 | (on an acceptable machine-readable medium) for up to three years 22 | at the cost of materials and delivery. Such redistributions must 23 | allow further use, modification, and redistribution of the Source 24 | Code under substantially the same terms as this license. For 25 | the purposes of redistribution "Source Code" means the complete 26 | human-readable, compilable, linkable, and operational source 27 | code of the redistributed module(s) including all modifications. 28 | 29 | 2. Redistributions of the Software Source Code must retain the 30 | copyright notices as they appear in each Source Code file, these 31 | license terms and conditions, and the disclaimer/limitation of 32 | liability set forth in paragraph 6 below. Redistributions of the 33 | Software Source Code must also comply with the copyright notices 34 | and/or license terms and conditions imposed by contributors on 35 | embedded code. The contributors' license terms and conditions 36 | and/or copyright notices are contained in the Source Code 37 | distribution. 38 | 39 | 3. Redistributions of the Software in binary form must reproduce the 40 | Copyright Notice described below, these license terms and conditions, 41 | and the disclaimer/limitation of liability set forth in paragraph 42 | 6 below, in the documentation and/or other materials provided with 43 | the binary distribution. For the purposes of binary distribution, 44 | "Copyright Notice" refers to the following language: "Copyright (c) 45 | 1998-2009 Sendmail, Inc. All rights reserved." 46 | 47 | 4. Neither the name, trademark or logo of Sendmail, Inc. (including 48 | without limitation its subsidiaries or affiliates) or its contributors 49 | may be used to endorse or promote products, or software or services 50 | derived from this Software without specific prior written permission. 51 | The name "sendmail" is a registered trademark and service mark of 52 | Sendmail, Inc. 53 | 54 | 5. We reserve the right to cancel this license if you do not comply with 55 | the terms. This license is governed by California law and both of us 56 | agree that for any dispute arising out of or relating to this Software, 57 | that jurisdiction and venue is proper in San Francisco or Alameda 58 | counties. These license terms and conditions reflect the complete 59 | agreement for the license of the Software (which means this supercedes 60 | prior or contemporaneous agreements or representations). If any term 61 | or condition under this license is found to be invalid, the remaining 62 | terms and conditions still apply. 63 | 64 | 6. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY 65 | SENDMAIL AND ITS CONTRIBUTORS "AS IS" WITHOUT WARRANTY OF ANY KIND 66 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 67 | IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A 68 | PARTICULAR PURPOSE ARE EXPRESSLY DISCLAIMED. IN NO EVENT SHALL SENDMAIL 69 | OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 70 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 71 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 72 | OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 73 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 74 | WITHOUT LIMITATION NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 75 | USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 76 | 77 | $Revision: 1.1 $ $Date: 2009/07/16 18:43:18 $ 78 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010-2014, 2016, 2017, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | AUTOMAKE_OPTIONS = foreign 5 | ACLOCAL_AMFLAGS = -I m4 6 | 7 | SUBDIRS = libopenarc contrib docs openarc 8 | dist_doc_DATA = LICENSE LICENSE.Sendmail RELEASE_NOTES 9 | dist_noinst_SCRIPTS = libtool 10 | 11 | DISTCLEANFILES = openarc-@VERSION@.tar.gz 12 | 13 | # TODO: get configure.ac to generate --enable-{feature} for all 14 | # non-experimental features and substitute it here e.g @SUPPORTED_FEATURES@. 15 | # Perhaps all features would enable a more comprehensive test coverage map 16 | # though. 17 | DISTCHECK_CONFIGURE_FLAGS=--with-openssl=/usr/local 18 | 19 | $(DIST_ARCHIVES): distcheck 20 | 21 | $(DIST_ARCHIVES).md5: $(DIST_ARCHIVES) 22 | md5 $? > $@ || md5sum $? > $@ 23 | 24 | $(DIST_ARCHIVES).sha1: $(DIST_ARCHIVES) 25 | sha1 $? > $@ || sha1sum $? > $@ 26 | 27 | $(DIST_ARCHIVES).asc: $(DIST_ARCHIVES) 28 | gpg -a -u security@trusteddomain.org --detach-sign $? 29 | 30 | push: $(DIST_ARCHIVES) $(DIST_ARCHIVES).sha1 $(DIST_ARCHIVES).md5 $(DIST_ARCHIVES).asc 31 | @echo "Are you sure you want to tag and release $(DIST_ARCHIVES)? (y/n)" 32 | @read confirm && [ $$confirm = 'y' ] 33 | git tag rel-openarc-`echo $(VERSION) | sed 's/\./-/g'` 34 | git push --tags 35 | 36 | dist-hook: 37 | [ -f $(distdir)/libopenarc/arc.h ] && rm -f $(distdir)/libopenarc/arc.h 38 | sed -e '/OPENARC_LIB_VERSION/s/0x[0-9]*/0x@HEX_VERSION@/' < $(srcdir)/libopenarc/arc.h > $(distdir)/libopenarc/arc.h 39 | echo "looking to see if @VERSION@ is in the RELEASE_NOTES" 40 | fgrep @VERSION@ $(srcdir)/RELEASE_NOTES 41 | sed -e 's|\(@VERSION@[ \t]*\)[0-9?]\{4\}\(/[0-9?]\{2\}\)\{2\}|\1'`date +%Y/%m/%d`'|' < $(srcdir)/RELEASE_NOTES > $(distdir)/RELEASE_NOTES 42 | 43 | rpm: dist-gzip 44 | rpmbuild -ta $(distdir).tar.gz 45 | 46 | .PHONY: push 47 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | OPENARC README 2 | ============== 3 | 4 | This directory has the latest open source ARC filter software from The 5 | Trusted Domain Project. 6 | 7 | There is a web site at http://www.trusteddomain.org that is home for the 8 | latest updates. 9 | 10 | 11 | +--------------+ 12 | | INTRODUCTION | 13 | +--------------+ 14 | 15 | The Trusted Domain Project (TDP) is a non-profit corporation dedicated to 16 | research and development of technologies that promote trust in the use of 17 | domain names in on the Internet. OpenARC is an initiative of TDP, and is 18 | primarily community effort to develop and maintain an open source library 19 | for producing ARC-aware applications, and a "milter"-based filter for 20 | providing ARC service. 21 | 22 | ARC is a technology proposal, put forward by a consortium of organizations, 23 | intended to allow a chain of message handlers (typically email operators) 24 | to confirm handling by trusted upstream handlers in an attempt to confirm 25 | the valid use of certain identifiers in the message. 26 | 27 | ARC is still experimental, and its specification may change. This package 28 | is intended for use by operators willing to take part in the experiment and 29 | provide their feedback to the development team. 30 | 31 | "milter" is a portmanteau of "mail filter" and refers to a protocol and API 32 | for communicating mail traffic information between MTAs and mail filtering 33 | plug-in applications. It was originally invented at Sendmail, Inc. but 34 | has also been adapted to other MTAs. 35 | 36 | A substantial amount of the code here is based on code developed as part of 37 | The OpenDKIM Project, also a TDP activity, which started as a code fork of 38 | version 2.8.3 of the open source "dkim-milter" package developed and 39 | maintained by Sendmail, Inc. The license used by The OpenDKIM Project is 40 | found in the LICENSE file. Portions of this project are also covered by the 41 | Sendmail Open Source License, available in this distribution in the file 42 | "LICENSE.Sendmail". See the copyright notice(s) in each source file to 43 | determine whether or not it is covered by both licenses. 44 | 45 | This package consists of a library that implements the ARC service and a 46 | milter-based filter application that can plug in to any milter-aware MTA to 47 | provide that service to sufficiently recent sendmail, Postfix or other MTAs 48 | that support the milter protocol. 49 | 50 | 51 | +--------------+ 52 | | DEPENDENCIES | 53 | +--------------+ 54 | 55 | To compile and operate, this package requires the following: 56 | 57 | o OpenSSL (http://www.openssl.org, or ask your software vendor for a package). 58 | Any version will get you started, however v0.9.8 or later is required if 59 | you want to be able to sign or verify messages using the SHA256 message 60 | digest algorithm which is generally required for current DKIM applications. 61 | 62 | o sendmail v8.13.0 (or later), or Postfix 2.3, (or later) and libmilter. 63 | (These are only required if you are building the filter.) 64 | 65 | o Access to a working nameserver (required only for signature verification). 66 | 67 | o On Linux systems, either libbsd (BSD compatibility library) or some other 68 | library that provides strlcat() and strlcpy(). 69 | 70 | o If you are interested in tinkering with the build and packaging structure, 71 | you may need to upgrade to these versions of GNU's "autotools" components: 72 | autoconf (GNU Autoconf) 2.61 73 | automake (GNU automake) 1.7 (or 1.9 to avoid warnings) 74 | ltmain.sh (GNU libtool) 2.2.6 (or 1.5.26 after make maintainer-clean) 75 | 76 | 77 | +-----------------------+ 78 | | RELATED DOCUMENTATION | 79 | +-----------------------+ 80 | 81 | The man page for openarc (the actual filter program) is present in the 82 | openarc directory of this source distribution. There is additional 83 | information in the INSTALL and FEATURES files, and in the README file in the 84 | openarc directory. Changes are documented in the RELEASE_NOTES file. 85 | 86 | HTML-style documentation for libarc is available in libarc/docs in 87 | this source distribution. 88 | 89 | Mailing lists discussing and supporting the ARC software found in this 90 | package are maintained via a list server at trusteddomain.org. Visit 91 | http://www.trusteddomain.org to subscribe or browse archives. The available 92 | lists are: 93 | 94 | openarc-announce (moderated) Release announcements. 95 | 96 | openarc-users General OpenARC user questions and answers. 97 | 98 | openarc-dev Chatter among OpenARC developers. 99 | 100 | Bug tracking is done via the issue trackers on GitHub, at 101 | https://github.com/mskucherawy/OpenARC/issues. You can enter new bug 102 | reports there, but please check first for older bugs already open, 103 | or even already closed, before opening a new issue. 104 | 105 | 106 | +---------+ 107 | | WARNING | 108 | +---------+ 109 | 110 | Since OpenARC uses cryptography, the following information from OpenSSL 111 | applies to this package as well. 112 | 113 | PLEASE REMEMBER THAT EXPORT/IMPORT AND/OR USE OF STRONG CRYPTOGRAPHY 114 | SOFTWARE, PROVIDING CRYPTOGRAPHY HOOKS OR EVEN JUST COMMUNICATING 115 | TECHNICAL DETAILS ABOUT CRYPTOGRAPHY SOFTWARE IS ILLEGAL IN SOME 116 | PARTS OF THE WORLD. SO, WHEN YOU IMPORT THIS PACKAGE TO YOUR 117 | COUNTRY, RE-DISTRIBUTE IT FROM THERE OR EVEN JUST EMAIL TECHNICAL 118 | SUGGESTIONS OR EVEN SOURCE PATCHES TO THE AUTHOR OR OTHER PEOPLE 119 | YOU ARE STRONGLY ADVISED TO PAY CLOSE ATTENTION TO ANY EXPORT/IMPORT 120 | AND/OR USE LAWS WHICH APPLY TO YOU. THE AUTHORS ARE NOT LIABLE FOR 121 | ANY VIOLATIONS YOU MAKE HERE. SO BE CAREFUL, IT IS YOUR RESPONSIBILITY. 122 | 123 | If you use OpenSSL then make sure you read their README file which 124 | contains information about patents etc. 125 | 126 | 127 | +---------------------+ 128 | | DIRECTORY STRUCTURE | 129 | +---------------------+ 130 | 131 | contrib A collection of user contributed scripts that may be useful. 132 | 133 | docs A collection of RFCs and drafts related to opendkim. 134 | 135 | libopenarc A library that implements the proposed ARC service. 136 | 137 | libopenarc/docs HTML documentation describing the API provided by libopenarc. 138 | 139 | openarc A milter-based filter application which uses libopenarc 140 | to provide ARC service via an MTA using the milter protocol. 141 | 142 | 143 | +----------------+ 144 | | RUNTIME ISSUES | 145 | +----------------+ 146 | 147 | WARNING: symbol 'X' not available 148 | 149 | The filter attempted to get some information from the MTA that the MTA 150 | did not provide. 151 | 152 | At various points in the interaction between the MTA and the filter, certain 153 | macros containing information about the job in progress or the connection 154 | being handled are passed from the MTA to the filter. 155 | 156 | In the case of sendmail, the names of the macros the MTA should pass to the 157 | filter are defined by the "Milter.macros" settings in sendmail.cf, e.g. 158 | "Milter.macros.connect", "Milter.macros.envfrom", etc. This message 159 | indicates that the filter needed the contents of macro X, but that macro 160 | was not passed down from the MTA. 161 | 162 | Typically the values needed by this filter are passed from the MTA if the 163 | sendmail.cf was generated by the usual m4 method. If you do not have 164 | those options defined in your sendmail.cf, make sure your M4 configuration 165 | files are current and rebuild your sendmail.cf to get appropriate lines 166 | added to your sendmail.cf, and then restart sendmail. 167 | 168 | MTA timeouts 169 | 170 | By default, the MTA is configured to wait up to ten seconds for a response 171 | from a filter before giving up. When querying remote nameservers 172 | for key and policy data, the ARC filter may not get a response from the 173 | resolver within that time frame, and thus this MTA timeout will occur. 174 | This can cause messages to be rejected, temp-failed or delivered without 175 | verification, depending on the failure mode selected for the filter. 176 | 177 | When using the standard resolver library provided with your system, the 178 | DNS timeout cannot be adjusted. If you encounter this problem, you must 179 | increase the time the MTA waits for replies. See the documentation in 180 | the sendmail open source distribution (libmilter/README in particular) 181 | for instructions on changing these timeouts. 182 | 183 | d2i_PUBKEY_bio() failed 184 | 185 | After retrieving and decoding a public key to perform a message verification, 186 | the OpenSSL library attempted to make use of that key but failed. The 187 | known possible causes are: 188 | 189 | (a) Memory exhaustion 190 | 191 | (b) Key corruption 192 | 193 | If you're set to temp-fail messages in these cases, the remote end will 194 | probably retry the message. If the same message fails again later, 195 | the key is probably corrupted or otherwise invalid. 196 | 197 | Other OpenARC issues: 198 | 199 | Report any bugs to the email address openarc-users@trusteddomain.org or to 200 | the GitHub issue trackers accessible at: 201 | 202 | https://github.com/mskucherawy/OpenARC/issues 203 | 204 | 205 | +-----------------------------+ 206 | | Sendmail REWRITING FEATURES | 207 | +-----------------------------+ 208 | 209 | There are two features of the sendmail MTA which, if activated, can interfere 210 | with successful use of the DKIM service. The two features are MASQUERADE_AS 211 | and FEATURE(genericstable). See cf/README in the open source sendmail 212 | source code distribution for more information. 213 | 214 | Due to the way the milter protocol is incorporated into the MTA, openarc 215 | sees the headers before they are modified as required by those two features. 216 | This means any signature is generated based on the headers originally 217 | injected by the mail client and not on the headers which are actually sent 218 | out by the MTA. As a result, the verifying agent at the receiver's side 219 | will be unable to verify the signature as the signed data and the received 220 | data don't match. 221 | 222 | The suggested solutions to this problem are: 223 | 224 | (1) Send mail with the headers already written as needed, obviating the 225 | need for these features (or just turn them off). 226 | 227 | (2) Have two MTAs set up, either on separate boxes or on the same box. 228 | The first MTA should do all of the rewriting (i.e. use these two 229 | features) and the second one should use opendkim to add the signature 230 | and do no rewriting at all. 231 | 232 | (3) Have multiple DaemonPortOptions lines in your configuration file. The 233 | first daemon port (port 25) does the header rewriting and then routes 234 | the message to the second port; the latter does no rewriting but does the 235 | signing and then sends the message on its way. 236 | 237 | There is also a feature of Sendmail that will cause it to alter addresses 238 | after signing but before they are transmitted. The feature, which is on 239 | by default, passes addresses in header fields to the resolver functions 240 | to ensure they are canonical. This can result in the replacement of those 241 | strings in the sent message with their canonical forms only after the message 242 | is signed, which will invalidate the signatures. To suppress this feature, 243 | add the following line to your sendmail.mc and submit.mc configuration files, 244 | re-generate your configuration and restart the filter: 245 | 246 | FEATURE(`nocanonify') 247 | 248 | -- 249 | Copyright (c) 2010-2012, 2014, 2016, 2017, The Trusted Domain Project. 250 | All rights reserved. 251 | -------------------------------------------------------------------------------- /RELEASE_NOTES: -------------------------------------------------------------------------------- 1 | OPENARC RELEASE NOTES 2 | 3 | This listing shows the versions of the OpenARC package, the date of 4 | release, and a summary of the changes in that release. 5 | 6 | 0.1.0 2017/12/06 7 | Initial pre-release. 8 | -------------------------------------------------------------------------------- /contrib/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | SUBDIRS = docs init spec systemd 5 | -------------------------------------------------------------------------------- /contrib/docs/Makefile.am: -------------------------------------------------------------------------------- 1 | dist_doc_DATA=draft-andersen-arc-05.txt 2 | -------------------------------------------------------------------------------- /contrib/init/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | AUTOMAKE_OPTIONS = foreign 5 | 6 | SUBDIRS = generic redhat solaris 7 | -------------------------------------------------------------------------------- /contrib/init/generic/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | dist_doc_DATA = openarc 5 | -------------------------------------------------------------------------------- /contrib/init/generic/README: -------------------------------------------------------------------------------- 1 | This directory contains a generic start/stop script that can be used on 2 | most UNIX systems to automate control of the openarc filter. 3 | 4 | To install, copy it to /etc/init.d/openarc, and ensure its mode is 0755. 5 | Then, follow the section below appropriate to your system. If you don't see 6 | your system listed, we would appreciate receiving from you instructions 7 | specific to your system once you get it working so that others who come 8 | after you can have helpful instructions. 9 | 10 | Please submit bug reports and feature requests to 11 | openarc-users@lists.trustedomain.org or via the trackers on SourceForge. 12 | 13 | 14 | RHEL-based and SLES-based Linux systems: 15 | 16 | Execute "chkconfig --add openarc" as root. This will read parameters found 17 | in the script and set up symbolic links under /etc/rc.d so that the filter 18 | is automatically started and stopped as needed. 19 | 20 | -- 21 | Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 22 | All rights reserved. 23 | -------------------------------------------------------------------------------- /contrib/init/generic/openarc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 4 | # All rights reserved. 5 | # 6 | # 7 | ### BEGIN INIT INFO 8 | # Provides: openarc 9 | # Required-Start: $syslog $time $local_fs $remote_fs $named $network 10 | # Required-Stop: $syslog $time $local_fs $remote_fs $named 11 | # Default-Start: 2 3 4 5 12 | # Default-Stop: S 0 1 6 13 | # Short-Description: OpenARC Milter 14 | # Description: The OpenARC milter for signing and verifying email 15 | # messages using the DomainKeys Identified Mail protocol 16 | ### END INIT INFO 17 | # 18 | # chkconfig: 345 20 80 19 | # description: OpenARC milter for signing and verifying email 20 | # processname: openarc 21 | # 22 | # This script should run successfully on any LSB-compliant system. It will 23 | # attempt to fall back to RedHatisms if LSB isn't available, or to 24 | # commonly-available utilities if it's not even RedHat. 25 | 26 | NAME=openarc 27 | PATH=/bin:/usr/bin:/sbin:/usr/sbin 28 | DAEMON=/usr/sbin/$NAME 29 | PIDFILE=/var/run/$NAME/$NAME.pid 30 | CONFIG=/etc/$NAME.conf 31 | USER=openarc 32 | 33 | # Implement our own status function per LSB specs. This will be used on 34 | # non-RedHat systems. 35 | od_status() { 36 | pid=$(od_getpid) 37 | if [ $? -ne 0 ]; then 38 | if [ -f $PIDFILE ]; then 39 | echo "$NAME dead but pid file exists" 40 | return 1 41 | elif [ -d /var/lock/subsys -a -f /var/lock/subsys/$NAME ]; then 42 | echo "$NAME dead but subsys locked" 43 | return 2 44 | else 45 | echo "$NAME is stopped" 46 | return 3 47 | fi 48 | fi 49 | echo "$NAME (pid $pid) is running..." 50 | return 0 51 | } 52 | 53 | od_getpid() { 54 | if [ -n "$1" -a "$1" = "-P" ]; then 55 | shift 56 | PIDFILE=$1 57 | shift 58 | else 59 | PIDFILE=$(grep -i '^pidfile' $CONFIG | head -n 1 | awk '{print $2}') 60 | fi 61 | if [ ! -f "$PIDFILE" ]; then 62 | return 1 63 | fi 64 | PID=$(cat "$PIDFILE") 65 | if [ -n "$(which pgrep)" ]; then 66 | for p in $(pgrep -f $DAEMON); do 67 | if [ "$PID" = "$p" ]; then 68 | echo $p 69 | return 0 70 | fi 71 | done 72 | elif [ -x "/bin/pidof" ]; then 73 | for p in $(/bin/pidof -o %PPID $DAEMON); do 74 | if [ "$PID" = "$p" ]; then 75 | echo $p 76 | return 0 77 | fi 78 | done 79 | fi 80 | return 1 81 | } 82 | 83 | od_killproc() { 84 | [ -z "$1" ] && return 1 85 | if [ -n "$2" ]; then 86 | signal=$2 87 | else 88 | signal="TERM" 89 | fi 90 | if $(od_getpid); then 91 | pkill -"$signal" -f $1 92 | fi 93 | } 94 | 95 | # Check for helper functions 96 | if [ -f /lib/lsb/init-functions ]; then 97 | # Use LSB functions, if available 98 | . /lib/lsb/init-functions 99 | alias od_killproc=killproc 100 | alias od_daemon=start_daemon 101 | elif [ -f /etc/init.d/functions ]; then 102 | # Use RedHat init functions if LSB isn't available 103 | . /etc/init.d/functions 104 | alias od_daemon=daemon 105 | alias log_success_msg=success 106 | alias log_warning_msg=passed 107 | alias log_failure_msg=failure 108 | alias od_killproc=killproc 109 | alias od_status=status 110 | elif [ -f /etc/rc.d/init.d/functions ]; then 111 | # Legacy RedHat init location 112 | . /etc/rc.d/init.d/functions 113 | alias od_daemon=daemon 114 | alias log_success_msg=success 115 | alias log_warning_msg=passed 116 | alias log_failure_msg=failure 117 | alias od_killproc=killproc 118 | alias od_status=status 119 | else 120 | # If all else fails, use generic commands 121 | alias od_daemon='' 122 | alias log_success_msg=echo 123 | alias log_warning_msg=echo 124 | alias log_failure_msg=echo 125 | fi 126 | 127 | if [ ! -x "$DAEMON" ]; then 128 | exit 5 129 | fi 130 | 131 | if [ ! -f "$CONFIG" ]; then 132 | log_failure_msg "$CONFIG not found" 133 | exit 6 134 | fi 135 | 136 | [ -r /etc/default/$NAME ] && . /etc/default/$NAME 137 | 138 | ARGS="-u $USER $ARGS" 139 | 140 | if [ -n "$SOCKET" ]; then 141 | ARGS="$ARGS -p $SOCKET" 142 | fi 143 | 144 | od_start() { 145 | echo -n "Starting OpenARC Milter: " 146 | od_daemon $DAEMON -c $CONFIG $ARGS 147 | if [ $? -eq 0 ]; then 148 | log_success_msg $NAME 149 | if [ -d /var/lock/subsys ]; then 150 | touch /var/lock/subsys/$NAME 151 | fi 152 | else 153 | log_failure_msg $NAME 154 | fi 155 | echo 156 | } 157 | 158 | od_stop() { 159 | echo -n "Stopping OpenARC Milter: " 160 | CPIDFILE="" 161 | if [ -f $CONFIG ]; then 162 | CPIDFILE=$(grep -i '^pidfile' $CONFIG | head -n 1 | awk '{print $2}') 163 | fi 164 | if [ x"$CPIDFILE" != x"" ]; then 165 | PIDFILE=$CPIDFILE 166 | fi 167 | 168 | od_killproc -p $CPIDFILE $DAEMON 169 | if [ $? -eq 0 ]; then 170 | log_success_msg $NAME 171 | if [ -d /var/lock/subsys ]; then 172 | rm -f /var/lock/subsys/$NAME 173 | fi 174 | else 175 | log_failure_msg $NAME 176 | fi 177 | echo 178 | } 179 | 180 | od_reload() { 181 | echo -n "Reloading OpenARC Milter configuration: " 182 | od_killproc $DAEMON USR1 183 | if [ $? -eq 0 ]; then 184 | log_success_msg $NAME 185 | else 186 | log_failure_msg $NAME 187 | fi 188 | echo 189 | } 190 | 191 | case "$1" in 192 | start) 193 | od_start 194 | ;; 195 | 196 | stop) 197 | od_stop 198 | ;; 199 | 200 | restart|force-reload) 201 | od_stop 202 | od_start 203 | ;; 204 | 205 | reload) 206 | od_reload 207 | ;; 208 | 209 | status) 210 | od_status $NAME 211 | ;; 212 | esac 213 | -------------------------------------------------------------------------------- /contrib/init/redhat/.gitignore: -------------------------------------------------------------------------------- 1 | openarc 2 | -------------------------------------------------------------------------------- /contrib/init/redhat/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010, 2011, 2013, 2016, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | dist_doc_DATA = openarc 5 | -------------------------------------------------------------------------------- /contrib/init/redhat/openarc.in: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # openarc Start and stop OpenARC. 4 | 5 | # chkconfig: - 41 59 6 | # description: OpenARC implements the Authenticated Received Chain (ARC) 7 | # service and a milter-based filter application that can plug 8 | # in to any milter-aware MTA. 9 | # processname: openarc 10 | # pidfile: /var/run/openarc/openarc.pid 11 | 12 | ### BEGIN INIT INFO 13 | # Provides: openarc 14 | # Short-Description: Start and stop OpenARC 15 | # Description: OpenARC implements the Authenticated Received Chain 16 | # (ARC) service and a milter-based filter application 17 | # that can plug in to any milter-aware MTA. 18 | ### END INIT INFO 19 | 20 | # OpenARC startup script v2.0 for RHEL/CentOS/Fedora 21 | # by Steve Jenkins (SteveJenkins.com) - 03-24-2015 22 | 23 | . /etc/rc.d/init.d/functions 24 | 25 | prefix=@prefix@ 26 | exec_prefix=@exec_prefix@ 27 | 28 | RETVAL=0 29 | prog="openarc" 30 | 31 | DAEMON=@sbindir@/$prog 32 | CONF_FILE=@sysconfdir@/$prog.conf 33 | PID_FILE=@localstatedir@/run/$prog/$prog.pid 34 | 35 | if [ -f /etc/sysconfig/openarc ]; then 36 | . /etc/sysconfig/openarc 37 | fi 38 | 39 | start() { 40 | echo -n $"Starting OpenARC Milter: " 41 | if [ -f $PID_FILE ]; then 42 | PID=`cat $PID_FILE` 43 | echo OpenARC already running as pid $PID 44 | exit 2; 45 | else 46 | daemon $DAEMON -c $CONF_FILE -P $PID_FILE 47 | RETVAL=$? 48 | [ $RETVAL -eq 0 ] && touch /var/lock/subsys/openarc 49 | echo 50 | return $RETVAL 51 | fi 52 | } 53 | 54 | stop() { 55 | echo -n $"Stopping OpenARC Milter: " 56 | killproc -p $PID_FILE openarc 57 | RETVAL=$? 58 | echo 59 | [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/openarc 60 | return $RETVAL 61 | } 62 | 63 | restart() { 64 | stop 65 | start 66 | } 67 | 68 | reload() { 69 | echo -n $"Reloading OpenARC Milter configuration: " 70 | killproc -p $PID_FILE openarc -SIGUSR1 71 | RETVAL=$? 72 | echo 73 | return $RETVAL 74 | } 75 | 76 | case "$1" in 77 | start) 78 | start 79 | ;; 80 | stop) 81 | stop 82 | ;; 83 | reload) 84 | reload 85 | ;; 86 | restart) 87 | restart 88 | ;; 89 | status) 90 | status -p $PID_FILE openarc 91 | ;; 92 | condrestart) 93 | [ -f /var/lock/subsys/openarc ] && restart || : 94 | ;; 95 | *) 96 | echo $"Usage: $0 {start|stop|status|reload|restart|condrestart}" 97 | exit 1 98 | esac 99 | 100 | exit $? 101 | -------------------------------------------------------------------------------- /contrib/init/solaris/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | dist_doc_DATA = openarc openarc.xml 5 | -------------------------------------------------------------------------------- /contrib/init/solaris/openarc: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | # 3 | # Start method script for the ARC milter 4 | # 5 | 6 | PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin; export PATH 7 | 8 | . /lib/svc/share/smf_include.sh 9 | 10 | echo "starting openarc" 11 | openarc -x /etc/mail/openarc.conf 12 | echo "started openarc" 13 | exit $SMF_EXIT_OK 14 | 15 | #!/end 16 | -------------------------------------------------------------------------------- /contrib/init/solaris/openarc.xml: -------------------------------------------------------------------------------- 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 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /contrib/spec/.gitignore: -------------------------------------------------------------------------------- 1 | openarc.spec 2 | -------------------------------------------------------------------------------- /contrib/spec/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010, 2011, 2016, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | AUTOMAKE_OPTIONS = foreign 5 | 6 | dist_doc_DATA = openarc.spec.in 7 | 8 | EXTRA_DIST = openarc.spec 9 | -------------------------------------------------------------------------------- /contrib/spec/openarc.spec.in: -------------------------------------------------------------------------------- 1 | %global systemd (0%{?fedora} >= 18) || (0%{?rhel} >= 7) 2 | %global tmpfiles (0%{?fedora} >= 15) || (0%{?rhel} >= 7) 3 | 4 | Summary: An open source library and milter for providing ARC service 5 | Name: openarc 6 | Version: @VERSION@ 7 | Release: 1%{?dist} 8 | License: BSD and Sendmail 9 | URL: https://github.com/mskucherawy/OpenARC 10 | 11 | BuildRequires: libtool 12 | BuildRequires: pkgconfig(openssl) 13 | BuildRequires: pkgconfig(libbsd) 14 | 15 | # sendmail-devel renamed for F25+ 16 | %if 0%{?fedora} > 25 17 | BuildRequires: sendmail-milter-devel 18 | %else 19 | BuildRequires: sendmail-devel 20 | %endif 21 | 22 | Requires: lib%{name}%{?_isa} = %{version}-%{release} 23 | Requires: libopenarc = %{version}-%{release} 24 | Requires(pre): shadow-utils 25 | %if %systemd 26 | # Required for systemd 27 | %{?systemd_requires} 28 | BuildRequires: systemd 29 | %else 30 | # Required for SysV 31 | Requires(post): chkconfig 32 | Requires(preun): chkconfig, initscripts 33 | Requires(postun): initscripts 34 | %endif 35 | 36 | Source0: openarc-%{version}.tar.gz 37 | Prefix: %{_prefix} 38 | 39 | %description 40 | The Trusted Domain Project is a community effort to develop and maintain a 41 | C library for producing ARC-aware applications and an open source milter for 42 | providing ARC service through milter-enabled MTAs. 43 | 44 | %package -n libopenarc 45 | Summary: An open source ARC library 46 | 47 | %description -n libopenarc 48 | This package contains the library files required for running services built 49 | using libopenarc. 50 | 51 | %package -n libopenarc-devel 52 | Summary: Development files for libopenarc 53 | Requires: lib%{name}%{?_isa} = %{version}-%{release} 54 | 55 | %description -n libopenarc-devel 56 | This package contains the static libraries, headers, and other support files 57 | required for developing applications against libopenarc. 58 | 59 | %prep 60 | %autosetup -p1 61 | 62 | %build 63 | %configure --disable-static 64 | 65 | make %{?_smp_mflags} 66 | %install 67 | make install DESTDIR=%{buildroot} 68 | mkdir -p %{buildroot}%{_sysconfdir} 69 | mkdir -p -m 0700 %{buildroot}%{_localstatedir}/run/%{name} 70 | rm -r %{buildroot}%{_prefix}/share/doc/openarc 71 | rm %{buildroot}/%{_libdir}/*.la 72 | 73 | 74 | cat > %{buildroot}%{_sysconfdir}/openarc.conf < %{buildroot}%{_unitdir}/%{name}.service << 'EOF' 96 | [Unit] 97 | Description=Authenticated Receive Chain (ARC) Milter 98 | Documentation=man:%{name}(8) man:%{name}.conf(5) http://www.trusteddomain.org/%{name}/ 99 | After=network.target nss-lookup.target syslog.target 100 | 101 | [Service] 102 | Type=forking 103 | PIDFile=%{_localstatedir}/run/%{name}/%{name}.pid 104 | EnvironmentFile=-%{_sysconfdir}/sysconfig/%{name} 105 | ExecStart=/usr/sbin/%{name} $OPTIONS 106 | ExecReload=/bin/kill -USR1 $MAINPID 107 | User=%{name} 108 | Group=%{name} 109 | 110 | [Install] 111 | WantedBy=multi-user.target 112 | EOF 113 | %else 114 | mkdir -p %{buildroot}%{_initrddir} 115 | install -m 0755 contrib/init/redhat/%{name} %{buildroot}%{_initrddir}/%{name} 116 | %endif 117 | 118 | %if %{tmpfiles} 119 | install -p -d %{buildroot}%{_tmpfilesdir} 120 | cat > %{buildroot}%{_tmpfilesdir}/%{name}.conf </dev/null 2>&1; then 127 | %{_sbindir}/useradd -M -d %{_localstatedir}/lib -r -s /bin/false openarc 128 | if ! getent group openarc >/dev/null; then 129 | %{_sbindir}/groupadd openarc 130 | %{_sbindir}/usermod -g openarc openarc 131 | fi 132 | if getent group mail >/dev/null; then 133 | %{_sbindir}/usermod -G mail openarc 134 | fi 135 | fi 136 | exit 0 137 | 138 | 139 | %post 140 | 141 | %if %systemd 142 | %systemd_post %{name}.service 143 | %else 144 | /sbin/chkconfig --add %{name} || : 145 | %endif 146 | 147 | 148 | %preun 149 | %if %systemd 150 | %systemd_preun %{name}.service 151 | %else 152 | if [ $1 -eq 0 ]; then 153 | service %{name} stop >/dev/null || : 154 | /sbin/chkconfig --del %{name} || : 155 | fi 156 | exit 0 157 | %endif 158 | 159 | %post -n libopenarc -p /sbin/ldconfig 160 | 161 | %postun -n libopenarc -p /sbin/ldconfig 162 | 163 | 164 | %files 165 | %defattr(-,root,root) 166 | %doc LICENSE LICENSE.Sendmail README RELEASE_NOTES 167 | %config(noreplace) %{_sysconfdir}/openarc.conf 168 | 169 | %if %{tmpfiles} 170 | %{_tmpfilesdir}/%{name}.conf 171 | %else 172 | %dir %attr(-,%{name},%{name}) %{_localstatedir}/run/%{name} 173 | %endif 174 | 175 | %if %{systemd} 176 | %{_unitdir}/%{name}.service 177 | %else 178 | %{_initrddir}/%{name} 179 | %endif 180 | %{_mandir}/*/* 181 | %{_sbindir}/* 182 | 183 | 184 | %files -n libopenarc 185 | %doc LICENSE LICENSE.Sendmail 186 | %defattr(-,root,root) 187 | %{_libdir}/*.so.* 188 | 189 | %files -n libopenarc-devel 190 | %defattr(-,root,root) 191 | %doc LICENSE LICENSE.Sendmail 192 | %{_includedir}/* 193 | %{_libdir}/*.so 194 | %{_libdir}/pkgconfig/*.pc 195 | 196 | %changelog 197 | * Sun Jul 23 2017 Matt Domsch 0.1.0-1 198 | - update to Fedora Packaging Guidelines 199 | -------------------------------------------------------------------------------- /contrib/systemd/.gitignore: -------------------------------------------------------------------------------- 1 | openarc.service 2 | -------------------------------------------------------------------------------- /contrib/systemd/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, The Trusted Domain Project. All rights reserved. 2 | 3 | dist_doc_DATA = openarc.service 4 | -------------------------------------------------------------------------------- /contrib/systemd/openarc.service.in: -------------------------------------------------------------------------------- 1 | # After=network.target nss-lookup.target syslog.target 2 | 3 | [Unit] 4 | Description=Authenticated Resource Chain (ARC) Milter 5 | Documentation=man:openarc(8) man:openarc.conf(5) http://www.trusteddomain.org/openarc 6 | After=network.target nss-lookup.target syslog.target 7 | 8 | [Service] 9 | Type=forking 10 | PIDFile=@localstatedir@/run/openarc/openarc.pid 11 | EnvironmentFile=-@sysconfdir@/sysconfig/openarc 12 | ExecStart=@sbindir@/openarc $OPTIONS 13 | ExecReload=/bin/kill -USR1 $MAINPID 14 | User=openarc 15 | Group=openarc 16 | 17 | [Install] 18 | WantedBy=multi-user.target 19 | -------------------------------------------------------------------------------- /copyright-check: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright (c) 2011-2014, 2017, The Trusted Domain Project. 4 | # All rights reserved. 5 | # 6 | 7 | YEAR=`date +%Y` 8 | LASTYEAR=$(($YEAR - 1)) 9 | 10 | for i in `git diff --name-only @{$LASTYEAR-12-31} | fgrep -v .jpg | fgrep -v contrib/ | fgrep -v m4/` 11 | do 12 | if test -f $i 13 | then 14 | if grep -q Copyright $i 15 | then 16 | if ! grep -q Copyright.\*$YEAR $i 17 | then 18 | echo $i 19 | fi 20 | fi 21 | fi 22 | done 23 | -------------------------------------------------------------------------------- /docs/Makefile.am: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trusteddomainproject/OpenARC/355ee2a1ca85acccce494478991983b54f794f4e/docs/Makefile.am -------------------------------------------------------------------------------- /libopenarc/.gitignore: -------------------------------------------------------------------------------- 1 | openarc.pc 2 | symbols.map 3 | .deps 4 | .libs 5 | -------------------------------------------------------------------------------- /libopenarc/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2016, 2017, The Trusted Domain Project. All rights reserved. 2 | 3 | #SUBDIRS=tests docs 4 | SUBDIRS=docs 5 | 6 | if DEBUG 7 | AM_CFLAGS = -g 8 | endif 9 | LDADD = ./libopenarc.la 10 | 11 | lib_LTLIBRARIES = libopenarc.la 12 | libopenarc_la_SOURCES = base64.c base64.h arc.c arc.h arc-canon.c arc-canon.h arc-dns.c arc-dns.h arc-internal.h arc-keys.c arc-keys.h arc-tables.c arc-tables.h arc-types.h arc-util.c arc-util.h 13 | libopenarc_la_CPPFLAGS = $(LIBCRYPTO_CPPFLAGS) 14 | libopenarc_la_CFLAGS = $(LIBCRYPTO_INCDIRS) $(LIBOPENARC_INC) 15 | libopenarc_la_LDFLAGS = -no-undefined $(LIBCRYPTO_LIBDIRS) -version-info $(LIBOPENARC_VERSION_INFO) 16 | libopenarc_la_LIBADD = $(LIBOPENARC_LIBS) $(LIBCRYPTO_LDADD) 17 | if !ALL_SYMBOLS 18 | libopenarc_la_DEPENDENCIES = symbols.map 19 | libopenarc_la_LDFLAGS += -export-symbols symbols.map 20 | endif 21 | if RPATH 22 | libopenarc_la_LDFLAGS += -rpath $(libdir) 23 | endif 24 | libopenarc_includedir = $(includedir)/openarc 25 | libopenarc_include_HEADERS = arc.h 26 | 27 | pkgconfigdir = $(libdir)/pkgconfig 28 | pkgconfig_DATA = openarc.pc 29 | 30 | DISTCLEANFILES=symbols.map *.gcno *.gcda 31 | 32 | symbols.map: $(libopenarc_include_HEADERS) 33 | grep '^extern' $? | \ 34 | awk '{ for (c = 1; c <= NF; c++) if ($$c ~ /arc_/) { print $$c; break; } }' | \ 35 | sed -e s/\[\*\;\]//g -e s/\[\\\[\\\]\]//g -e s/\(.*// | \ 36 | sort -u -o $@ 37 | 38 | MOSTLYCLEANFILES=symbols.map *.gcno *.gcda 39 | -------------------------------------------------------------------------------- /libopenarc/arc-canon.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2007, 2008 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009, 2011, 2012, 2017, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #ifndef _ARC_CANON_H_ 10 | #define _ARC_CANON_H_ 11 | 12 | #include "build-config.h" 13 | 14 | /* system includes */ 15 | #include 16 | #ifdef HAVE_STDBOOL_H 17 | # include 18 | #endif /* HAVE_STDBOOL_H */ 19 | 20 | /* libopenarc includes */ 21 | #include "arc.h" 22 | #include "arc-types.h" 23 | 24 | #define ARC_HASHBUFSIZE 4096 25 | 26 | #define ARC_CANONTYPE_HEADER 0 27 | #define ARC_CANONTYPE_BODY 1 28 | #define ARC_CANONTYPE_SEAL 2 29 | 30 | /* prototypes */ 31 | extern ARC_STAT arc_add_canon __P((ARC_MESSAGE *, int, arc_canon_t, int, 32 | u_char *, struct arc_hdrfield *, 33 | ssize_t length, ARC_CANON **)); 34 | extern ARC_STAT arc_canon_add_to_seal __P((ARC_MESSAGE *)); 35 | extern ARC_STAT arc_canon_bodychunk __P((ARC_MESSAGE *, u_char *, size_t)); 36 | extern void arc_canon_cleanup __P((ARC_MESSAGE *)); 37 | extern ARC_STAT arc_canon_closebody __P((ARC_MESSAGE *)); 38 | extern ARC_STAT arc_canon_getfinal __P((ARC_CANON *, u_char **, size_t *)); 39 | extern ARC_STAT arc_canon_gethashes __P((ARC_MESSAGE *, void **, size_t *, 40 | void **, size_t *)); 41 | extern ARC_STAT arc_canon_getsealhash __P((ARC_MESSAGE *, int, 42 | void **, size_t *)); 43 | extern ARC_STAT arc_canon_header_string __P((struct arc_dstring *, 44 | arc_canon_t, 45 | unsigned char *, 46 | size_t, _Bool)); 47 | extern ARC_STAT arc_canon_init __P((ARC_MESSAGE *, _Bool, _Bool)); 48 | extern u_long arc_canon_minbody __P((ARC_MESSAGE *)); 49 | extern ARC_STAT arc_canon_runheaders __P((ARC_MESSAGE *)); 50 | extern ARC_STAT arc_canon_runheaders_seal __P((ARC_MESSAGE *)); 51 | extern int arc_canon_selecthdrs __P((ARC_MESSAGE *, u_char *, 52 | struct arc_hdrfield **, int)); 53 | extern ARC_STAT arc_canon_signature __P((ARC_MESSAGE *, struct arc_hdrfield *, _Bool)); 54 | 55 | extern ARC_STAT arc_parse_canon_t(unsigned char *, arc_canon_t *, arc_canon_t *); 56 | 57 | #endif /* ! _ARC_CANON_H_ */ 58 | -------------------------------------------------------------------------------- /libopenarc/arc-dns.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2010-2012, 2017, The Trusted Domain Project. 3 | ** All rights reserved. 4 | */ 5 | 6 | /* for Solaris */ 7 | #ifndef _REENTRANT 8 | # define _REENTRANT 9 | #endif /* ! REENTRANT */ 10 | 11 | /* system includes */ 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* libopenarc includes */ 24 | #include "arc.h" 25 | #include "arc-dns.h" 26 | 27 | /* OpenARC includes */ 28 | #include "build-config.h" 29 | 30 | /* macros, limits, etc. */ 31 | #ifndef MAXPACKET 32 | # define MAXPACKET 8192 33 | #endif /* ! MAXPACKET */ 34 | 35 | /* 36 | ** Standard UNIX resolver stub functions 37 | */ 38 | 39 | struct arc_res_qh 40 | { 41 | int rq_error; 42 | int rq_dnssec; 43 | size_t rq_buflen; 44 | }; 45 | 46 | /* 47 | ** ARC_RES_INIT -- initialize the resolver 48 | ** 49 | ** Parameters: 50 | ** srv -- service handle (returned) 51 | ** 52 | ** Return value 53 | ** 0 on success, !0 on failure 54 | */ 55 | 56 | int 57 | arc_res_init(void **srv) 58 | { 59 | #ifdef HAVE_RES_NINIT 60 | struct __res_state *res; 61 | 62 | res = malloc(sizeof(struct __res_state)); 63 | if (res == NULL) 64 | return -1; 65 | 66 | memset(res, '\0', sizeof(struct __res_state)); 67 | 68 | if (res_ninit(res) != 0) 69 | { 70 | free(res); 71 | return -1; 72 | } 73 | 74 | *srv = res; 75 | 76 | return 0; 77 | #else /* HAVE_RES_NINIT */ 78 | if (res_init() == 0) 79 | { 80 | *srv = (void *) 0x01; 81 | return 0; 82 | } 83 | else 84 | { 85 | return -1; 86 | } 87 | #endif /* HAVE_RES_NINIT */ 88 | } 89 | 90 | /* 91 | ** ARC_RES_CLOSE -- shut down the resolver 92 | ** 93 | ** Parameters: 94 | ** srv -- service handle 95 | ** 96 | ** Return value: 97 | ** None. 98 | */ 99 | 100 | void 101 | arc_res_close(void *srv) 102 | { 103 | #ifdef HAVE_RES_NINIT 104 | struct __res_state *res; 105 | 106 | res = srv; 107 | 108 | if (res != NULL) 109 | { 110 | res_nclose(res); 111 | free(res); 112 | } 113 | #endif /* HAVE_RES_NINIT */ 114 | } 115 | 116 | /* 117 | ** ARC_RES_CANCEL -- cancel a pending resolver query 118 | ** 119 | ** Parameters: 120 | ** srv -- query service handle (ignored) 121 | ** qh -- query handle (ignored) 122 | ** 123 | ** Return value: 124 | ** 0 on success, !0 on error 125 | ** 126 | ** Notes: 127 | ** The standard UNIX resolver is synchronous, so in theory this can 128 | ** never get called. We have not yet got any use cases for one thread 129 | ** canceling another thread's pending queries, so for now just return 0. 130 | */ 131 | 132 | int 133 | arc_res_cancel(void *srv, void *qh) 134 | { 135 | if (qh != NULL) 136 | free(qh); 137 | 138 | return 0; 139 | } 140 | 141 | /* 142 | ** ARC_RES_QUERY -- initiate a DNS query 143 | ** 144 | ** Parameters: 145 | ** srv -- service handle (ignored) 146 | ** type -- RR type to query 147 | ** query -- the question to ask 148 | ** buf -- where to write the answer 149 | ** buflen -- bytes at "buf" 150 | ** qh -- query handle, used with arc_res_waitreply 151 | ** 152 | ** Return value: 153 | ** 0 on success, -1 on error 154 | ** 155 | ** Notes: 156 | ** This is a stub for the stock UNIX resolver (res_) functions, which 157 | ** are synchronous so no handle needs to be created, so "qh" is set to 158 | ** "buf". "buf" is actually populated before this returns (unless 159 | ** there's an error). 160 | */ 161 | 162 | int 163 | arc_res_query(void *srv, int type, unsigned char *query, unsigned char *buf, 164 | size_t buflen, void **qh) 165 | { 166 | int n; 167 | int ret; 168 | struct arc_res_qh *rq; 169 | unsigned char qbuf[HFIXEDSZ + MAXPACKET]; 170 | #ifdef HAVE_RES_NINIT 171 | struct __res_state *statp; 172 | #endif /* HAVE_RES_NINIT */ 173 | 174 | #ifdef HAVE_RES_NINIT 175 | statp = srv; 176 | n = res_nmkquery(statp, QUERY, (char *) query, C_IN, type, NULL, 0, 177 | NULL, qbuf, sizeof qbuf); 178 | #else /* HAVE_RES_NINIT */ 179 | n = res_mkquery(QUERY, (char *) query, C_IN, type, NULL, 0, NULL, qbuf, 180 | sizeof qbuf); 181 | #endif /* HAVE_RES_NINIT */ 182 | if (n == (size_t) -1) 183 | return ARC_DNS_ERROR; 184 | 185 | #ifdef HAVE_RES_NINIT 186 | ret = res_nsend(statp, qbuf, n, buf, buflen); 187 | #else /* HAVE_RES_NINIT */ 188 | ret = res_send(qbuf, n, buf, buflen); 189 | #endif /* HAVE_RES_NINIT */ 190 | if (ret == -1) 191 | return ARC_DNS_ERROR; 192 | 193 | rq = (struct arc_res_qh *) malloc(sizeof *rq); 194 | if (rq == NULL) 195 | return ARC_DNS_ERROR; 196 | 197 | rq->rq_dnssec = ARC_DNSSEC_UNKNOWN; 198 | if (ret == -1) 199 | { 200 | rq->rq_error = errno; 201 | rq->rq_buflen = 0; 202 | } 203 | else 204 | { 205 | rq->rq_error = 0; 206 | rq->rq_buflen = (size_t) ret; 207 | } 208 | 209 | *qh = (void *) rq; 210 | 211 | return ARC_DNS_SUCCESS; 212 | } 213 | 214 | /* 215 | ** ARC_RES_WAITREPLY -- wait for a reply to a pending query 216 | ** 217 | ** Parameters: 218 | ** srv -- service handle 219 | ** qh -- query handle 220 | ** to -- timeout 221 | ** bytes -- number of bytes in the reply (returned) 222 | ** error -- error code (returned) 223 | ** 224 | ** Return value: 225 | ** A ARC_DNS_* code. 226 | ** 227 | ** Notes: 228 | ** Since the stock UNIX resolver is synchronous, the reply was completed 229 | ** before arc_res_query() returned, and thus this is almost a no-op. 230 | */ 231 | 232 | int 233 | arc_res_waitreply(void *srv, void *qh, struct timeval *to, size_t *bytes, 234 | int *error, int *dnssec) 235 | { 236 | struct arc_res_qh *rq; 237 | 238 | assert(qh != NULL); 239 | 240 | rq = qh; 241 | 242 | if (bytes != NULL) 243 | *bytes = rq->rq_buflen; 244 | if (error != NULL) 245 | *error = rq->rq_error; 246 | if (dnssec != NULL) 247 | *dnssec = rq->rq_dnssec; 248 | 249 | return ARC_DNS_SUCCESS; 250 | } 251 | 252 | /* 253 | ** ARC_RES_SETNS -- set nameserver list 254 | ** 255 | ** Parameters: 256 | ** srv -- service handle 257 | ** nslist -- nameserver list, as a string 258 | ** 259 | ** Return value: 260 | ** ARC_DNS_SUCCESS -- success 261 | ** ARC_DNS_ERROR -- error 262 | */ 263 | 264 | int 265 | arc_res_nslist(void *srv, const char *nslist) 266 | { 267 | #ifdef HAVE_RES_SETSERVERS 268 | int nscount = 0; 269 | char *tmp; 270 | char *ns; 271 | char *last = NULL; 272 | struct sockaddr_in in; 273 | # ifdef AF_INET6 274 | struct sockaddr_in6 in6; 275 | # endif /* AF_INET6 */ 276 | struct state *res; 277 | res_sockaddr_union nses[MAXNS]; 278 | 279 | assert(srv != NULL); 280 | assert(nslist != NULL); 281 | 282 | memset(nses, '\0', sizeof nses); 283 | 284 | tmp = strdup(nslist); 285 | if (tmp == NULL) 286 | return ARC_DNS_ERROR; 287 | 288 | for (ns = strtok_r(tmp, ",", &last); 289 | ns != NULL && nscount < MAXNS; 290 | ns = strtok_r(NULL, ",", &last) 291 | { 292 | memset(&in, '\0', sizeof in); 293 | # ifdef AF_INET6 294 | memset(&in6, '\0', sizeof in6); 295 | # endif /* AF_INET6 */ 296 | 297 | if (inet_pton(AF_INET, ns, (struct in_addr *) &in.sin_addr, 298 | sizeof in.sin_addr) == 1) 299 | { 300 | in.sin_family= AF_INET; 301 | in.sin_port = htons(DNSPORT); 302 | memcpy(&nses[nscount].sin, &in, 303 | sizeof nses[nscount].sin); 304 | nscount++; 305 | } 306 | # ifdef AF_INET6 307 | else if (inet_pton(AF_INET6, ns, 308 | (struct in6_addr *) &in6.sin6_addr, 309 | sizeof in6.sin6_addr) == 1) 310 | { 311 | in6.sin6_family= AF_INET6; 312 | in6.sin6_port = htons(DNSPORT); 313 | memcpy(&nses[nscount].sin6, &in6, 314 | sizeof nses[nscount].sin6); 315 | nscount++; 316 | } 317 | # endif /* AF_INET6 */ 318 | else 319 | { 320 | free(tmp); 321 | return ARC_DNS_ERROR; 322 | } 323 | } 324 | 325 | res = srv; 326 | res_setservers(res, nses, nscount); 327 | 328 | free(tmp); 329 | #endif /* HAVE_RES_SETSERVERS */ 330 | 331 | return ARC_DNS_SUCCESS; 332 | } 333 | -------------------------------------------------------------------------------- /libopenarc/arc-dns.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2010, 2012, 2017, The Trusted Domain Project. 3 | ** All rights reserved. 4 | */ 5 | 6 | #ifndef _ARC_DNS_H_ 7 | #define _ARC_DNS_H_ 8 | 9 | /* libopenarc includes */ 10 | #include "arc.h" 11 | 12 | /* prototypes */ 13 | extern int arc_res_cancel __P((void *, void *)); 14 | extern void arc_res_close __P((void *)); 15 | extern int arc_res_init __P((void **)); 16 | extern int arc_res_nslist __P((void *, const char *)); 17 | extern int arc_res_query __P((void *, int, unsigned char *, unsigned char *, 18 | size_t, void **)); 19 | extern int arc_res_waitreply __P((void *, void *, struct timeval *, 20 | size_t *, int *, int *)); 21 | 22 | #endif /* ! _ARC_DNS_H_ */ 23 | -------------------------------------------------------------------------------- /libopenarc/arc-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, The Trusted Domain Project. 3 | ** All rights reserved. 4 | */ 5 | 6 | #ifndef _ARC_INTERNAL_H_ 7 | #define _ARC_INTERNAL_H_ 8 | 9 | /* libopenarc includes */ 10 | #include "arc.h" 11 | 12 | /* the basics */ 13 | #ifndef NULL 14 | # define NULL 0 15 | #endif /* ! NULL */ 16 | #ifndef FALSE 17 | # define FALSE 0 18 | #endif /* ! FALSE */ 19 | #ifndef TRUE 20 | # define TRUE 1 21 | #endif /* ! TRUE */ 22 | #ifndef MAXPATHLEN 23 | # define MAXPATHLEN 256 24 | #endif /* ! MAXPATHLEN */ 25 | 26 | #ifndef ULONG_MAX 27 | # define ULONG_MAX 0xffffffffL 28 | #endif /* ! ULONG_MAX */ 29 | #ifndef ULLONG_MAX 30 | # define ULLONG_MAX 0xffffffffffffffffLL 31 | #endif /* ! ULLONG_MAX */ 32 | 33 | #ifndef MIN 34 | # define MIN(x,y) ((x) < (y) ? (x) : (y)) 35 | #endif /* ! MIN */ 36 | #ifndef MAX 37 | # define MAX(x,y) ((x) > (y) ? (x) : (y)) 38 | #endif /* ! MAX */ 39 | 40 | #ifdef __STDC__ 41 | # ifndef __P 42 | # define __P(x) x 43 | # endif /* ! __P */ 44 | #else /* __STDC__ */ 45 | # ifndef __P 46 | # define __P(x) () 47 | # endif /* ! __P */ 48 | #endif /* __STDC__ */ 49 | 50 | /* limits, macros, etc. */ 51 | #define BUFRSZ 1024 /* base temp buffer size */ 52 | #define BASE64SIZE(x) (((x + 2) / 3) * 4) 53 | /* base64 encoding growth ratio */ 54 | #define MAXADDRESS 256 /* biggest user@host we accept */ 55 | #define MAXBUFRSZ 65536 /* max temp buffer size */ 56 | #define MAXCNAMEDEPTH 3 /* max. CNAME recursion we allow */ 57 | #define MAXHEADERS 32768 /* buffer for caching headers */ 58 | #define MAXLABELS 16 /* max. labels we allow */ 59 | #define MAXTAGNAME 8 /* biggest tag name */ 60 | 61 | #define NPRINTABLE 95 /* number of printable characters */ 62 | 63 | #define ARC_MAXHEADER 4096 /* buffer for caching one header */ 64 | #define ARC_MAXHOSTNAMELEN 256 /* max. FQDN we support */ 65 | 66 | /* defaults */ 67 | #define DEFTMPDIR "/tmp" /* default temporary directory */ 68 | 69 | /* 70 | ** ARC_KVSETTYPE -- types of key-value sets 71 | */ 72 | 73 | typedef int arc_kvsettype_t; 74 | 75 | #define ARC_KVSETTYPE_ANY (-1) 76 | #define ARC_KVSETTYPE_SIGNATURE 0 77 | #define ARC_KVSETTYPE_KEY 1 78 | #define ARC_KVSETTYPE_SEAL 2 79 | #define ARC_KVSETTYPE_AR 3 80 | #define ARC_KVSETTYPE_MAX 3 /* sentinel value */ 81 | 82 | /* 83 | ** ARC_HASHTYPE -- types of hashes 84 | */ 85 | 86 | #define ARC_HASHTYPE_UNKNOWN (-1) 87 | #define ARC_HASHTYPE_SHA1 0 88 | #define ARC_HASHTYPE_SHA256 1 89 | 90 | /* 91 | ** ARC_KEYTYPE -- types of keys 92 | */ 93 | 94 | #define ARC_KEYTYPE_UNKNOWN (-1) 95 | #define ARC_KEYTYPE_RSA 0 96 | 97 | /* 98 | ** ARC_QUERY -- types of queries 99 | */ 100 | 101 | #define ARC_QUERY_UNKNOWN (-1) 102 | #define ARC_QUERY_DNS 0 103 | 104 | /* 105 | ** ARC_KVSET -- a set of parameters and values 106 | */ 107 | 108 | struct arc_kvset; 109 | typedef struct arc_kvset ARC_KVSET; 110 | 111 | /* 112 | ** ARC_PLIST -- a parameter/value pair, as a linked list 113 | */ 114 | 115 | struct arc_plist; 116 | typedef struct arc_plist ARC_PLIST; 117 | 118 | /* 119 | ** ARC_CANON -- canonicalization 120 | */ 121 | 122 | struct arc_canon; 123 | typedef struct arc_canon ARC_CANON; 124 | 125 | #endif /* ! _ARC_INTERNAL_H_ */ 126 | -------------------------------------------------------------------------------- /libopenarc/arc-keys.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2015, 2017, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | /* system includes */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "build-config.h" 24 | 25 | /* libopendkim includes */ 26 | #include "arc-internal.h" 27 | #include "arc-types.h" 28 | #include "arc-keys.h" 29 | #include "arc-util.h" 30 | 31 | /* libbsd if found */ 32 | #ifdef USE_BSD_H 33 | # include 34 | #endif /* USE_BSD_H */ 35 | 36 | /* libstrl if needed */ 37 | #ifdef USE_STRL_H 38 | # include 39 | #endif /* USE_STRL_H */ 40 | 41 | /* prototypes */ 42 | extern void arc_error __P((ARC_MESSAGE *, const char *, ...)); 43 | 44 | /* local definitions needed for DNS queries */ 45 | #define MAXPACKET 8192 46 | #if defined(__RES) && (__RES >= 19940415) 47 | # define RES_UNC_T char * 48 | #else /* __RES && __RES >= 19940415 */ 49 | # define RES_UNC_T unsigned char * 50 | #endif /* __RES && __RES >= 19940415 */ 51 | #ifndef T_RRSIG 52 | # define T_RRSIG 46 53 | #endif /* ! T_RRSIG */ 54 | 55 | /* 56 | ** ARC_GET_KEY_DNS -- retrieve a key from DNS 57 | ** 58 | ** Parameters: 59 | ** msg -- ARC_MESSAGE handle 60 | ** buf -- buffer into which to write the result 61 | ** buflen -- bytes available at "buf" 62 | ** 63 | ** Return value: 64 | ** A ARC_STAT_* constant. 65 | */ 66 | 67 | ARC_STAT 68 | arc_get_key_dns(ARC_MESSAGE *msg, u_char *buf, size_t buflen) 69 | { 70 | int status; 71 | int qdcount; 72 | int ancount; 73 | int error; 74 | int dnssec = ARC_DNSSEC_UNKNOWN; 75 | int c; 76 | int n = 0; 77 | int rdlength = 0; 78 | int type = -1; 79 | int class = -1; 80 | size_t anslen; 81 | void *q; 82 | ARC_LIB *lib; 83 | unsigned char *txtfound = NULL; 84 | unsigned char *p; 85 | unsigned char *cp; 86 | unsigned char *eom; 87 | unsigned char *eob; 88 | unsigned char qname[ARC_MAXHOSTNAMELEN + 1]; 89 | unsigned char ansbuf[MAXPACKET]; 90 | struct timeval timeout; 91 | HEADER hdr; 92 | 93 | assert(msg != NULL); 94 | assert(msg->arc_selector != NULL); 95 | assert(msg->arc_domain != NULL); 96 | 97 | lib = msg->arc_library; 98 | 99 | n = snprintf((char *) qname, sizeof qname - 1, "%s.%s.%s", 100 | msg->arc_selector, ARC_DNSKEYNAME, msg->arc_domain); 101 | if (n == -1 || n > sizeof qname - 1) 102 | { 103 | arc_error(msg, "key query name too large"); 104 | return ARC_STAT_NORESOURCE; 105 | } 106 | 107 | anslen = sizeof ansbuf; 108 | 109 | timeout.tv_sec = msg->arc_timeout; 110 | timeout.tv_usec = 0; 111 | 112 | if (lib->arcl_dns_service == NULL && 113 | lib->arcl_dns_init != NULL && 114 | lib->arcl_dns_init(&lib->arcl_dns_service) != 0) 115 | { 116 | arc_error(msg, "cannot initialize resolver"); 117 | return ARC_STAT_KEYFAIL; 118 | } 119 | 120 | status = lib->arcl_dns_start(lib->arcl_dns_service, T_TXT, 121 | qname, ansbuf, anslen, &q); 122 | 123 | if (status != 0) 124 | { 125 | arc_error(msg, "'%s' query failed", qname); 126 | return ARC_STAT_KEYFAIL; 127 | } 128 | 129 | if (lib->arcl_dns_callback == NULL) 130 | { 131 | timeout.tv_sec = msg->arc_timeout; 132 | timeout.tv_usec = 0; 133 | 134 | status = lib->arcl_dns_waitreply(lib->arcl_dns_service, 135 | q, 136 | msg->arc_timeout == 0 ? NULL 137 | : &timeout, 138 | &anslen, &error, 139 | &dnssec); 140 | } 141 | else 142 | { 143 | struct timeval master; 144 | struct timeval next; 145 | struct timeval *wt; 146 | 147 | (void) gettimeofday(&master, NULL); 148 | master.tv_sec += msg->arc_timeout; 149 | 150 | for (;;) 151 | { 152 | (void) gettimeofday(&next, NULL); 153 | next.tv_sec += lib->arcl_callback_int; 154 | 155 | arc_min_timeval(&master, &next, 156 | &timeout, &wt); 157 | 158 | status = lib->arcl_dns_waitreply(lib->arcl_dns_service, 159 | q, 160 | msg->arc_timeout == 0 ? NULL 161 | : &timeout, 162 | &anslen, 163 | &error, 164 | &dnssec); 165 | 166 | if (wt == &next) 167 | { 168 | if (status == ARC_DNS_NOREPLY || 169 | status == ARC_DNS_EXPIRED) 170 | lib->arcl_dns_callback(msg->arc_user_context); 171 | else 172 | break; 173 | } 174 | else 175 | { 176 | break; 177 | } 178 | } 179 | } 180 | 181 | if (status == ARC_DNS_EXPIRED) 182 | { 183 | (void) lib->arcl_dns_cancel(lib->arcl_dns_service, q); 184 | arc_error(msg, "'%s' query timed out", qname); 185 | return ARC_STAT_KEYFAIL; 186 | } 187 | else if (status == ARC_DNS_ERROR) 188 | { 189 | (void) lib->arcl_dns_cancel(lib->arcl_dns_service, q); 190 | arc_error(msg, "'%s' query failed", qname); 191 | return ARC_STAT_KEYFAIL; 192 | } 193 | 194 | (void) lib->arcl_dns_cancel(lib->arcl_dns_service, q); 195 | 196 | msg->arc_dnssec_key = dnssec; 197 | 198 | /* set up pointers */ 199 | memcpy(&hdr, ansbuf, sizeof hdr); 200 | cp = (u_char *) &ansbuf + HFIXEDSZ; 201 | eom = (u_char *) &ansbuf + anslen; 202 | 203 | /* skip over the name at the front of the answer */ 204 | for (qdcount = ntohs((unsigned short) hdr.qdcount); 205 | qdcount > 0; 206 | qdcount--) 207 | { 208 | /* copy it first */ 209 | (void) dn_expand((unsigned char *) &ansbuf, eom, cp, 210 | (char *) qname, sizeof qname); 211 | 212 | if ((n = dn_skipname(cp, eom)) < 0) 213 | { 214 | arc_error(msg, "'%s' reply corrupt", qname); 215 | return ARC_STAT_KEYFAIL; 216 | } 217 | cp += n; 218 | 219 | /* extract the type and class */ 220 | if (cp + INT16SZ + INT16SZ > eom) 221 | { 222 | arc_error(msg, "'%s' reply corrupt", qname); 223 | return ARC_STAT_KEYFAIL; 224 | } 225 | GETSHORT(type, cp); 226 | GETSHORT(class, cp); 227 | } 228 | 229 | if (type != T_TXT || class != C_IN) 230 | { 231 | arc_error(msg, "'%s' unexpected reply class/type (%d/%d)", 232 | qname, class, type); 233 | return ARC_STAT_KEYFAIL; 234 | } 235 | 236 | /* if NXDOMAIN, return ARC_STAT_NOKEY */ 237 | if (hdr.rcode == NXDOMAIN) 238 | { 239 | arc_error(msg, "'%s' record not found", qname); 240 | return ARC_STAT_NOKEY; 241 | } 242 | 243 | /* if truncated, we can't do it */ 244 | if (arc_check_dns_reply(ansbuf, anslen, C_IN, T_TXT) == 1) 245 | { 246 | arc_error(msg, "'%s' reply truncated", qname); 247 | return ARC_STAT_KEYFAIL; 248 | } 249 | 250 | /* get the answer count */ 251 | ancount = ntohs((unsigned short) hdr.ancount); 252 | if (ancount == 0) 253 | return ARC_STAT_NOKEY; 254 | 255 | /* 256 | ** Extract the data from the first TXT answer. 257 | */ 258 | 259 | while (--ancount >= 0 && cp < eom) 260 | { 261 | /* grab the label, even though we know what we asked... */ 262 | if ((n = dn_expand((unsigned char *) &ansbuf, eom, cp, 263 | (RES_UNC_T) qname, sizeof qname)) < 0) 264 | { 265 | arc_error(msg, "'%s' reply corrupt", qname); 266 | return ARC_STAT_KEYFAIL; 267 | } 268 | /* ...and move past it */ 269 | cp += n; 270 | 271 | /* extract the type and class */ 272 | if (cp + INT16SZ + INT16SZ + INT32SZ + INT16SZ > eom) 273 | { 274 | arc_error(msg, "'%s' reply corrupt", qname); 275 | return ARC_STAT_KEYFAIL; 276 | } 277 | 278 | GETSHORT(type, cp); /* TYPE */ 279 | GETSHORT(class, cp); /* CLASS */ 280 | /* skip the TTL */ 281 | cp += INT32SZ; /* TTL */ 282 | GETSHORT(n, cp); /* RDLENGTH */ 283 | 284 | /* skip CNAME if found; assume it was resolved */ 285 | if (type == T_CNAME) 286 | { 287 | cp += n; 288 | continue; 289 | } 290 | else if (type == T_RRSIG) 291 | { 292 | cp += n; 293 | continue; 294 | } 295 | else if (type != T_TXT) 296 | { 297 | arc_error(msg, "'%s' reply was unexpected type %d", 298 | qname, type); 299 | return ARC_STAT_KEYFAIL; 300 | } 301 | 302 | if (txtfound != NULL) 303 | { 304 | arc_error(msg, "multiple DNS replies for '%s'", 305 | qname); 306 | return ARC_STAT_MULTIDNSREPLY; 307 | } 308 | 309 | /* remember where this one started */ 310 | txtfound = cp; 311 | rdlength = n; 312 | 313 | /* move forward for now */ 314 | cp += n; 315 | } 316 | 317 | /* if ancount went below 0, there were no good records */ 318 | if (txtfound == NULL) 319 | { 320 | arc_error(msg, "'%s' reply was unresolved CNAME", qname); 321 | return ARC_STAT_NOKEY; 322 | } 323 | 324 | /* come back to the one we found */ 325 | cp = txtfound; 326 | 327 | /* 328 | ** XXX -- maybe deal with a partial reply rather than require 329 | ** it all 330 | */ 331 | 332 | if (cp + rdlength > eom) 333 | { 334 | arc_error(msg, "'%s' reply corrupt", qname); 335 | return ARC_STAT_SYNTAX; 336 | } 337 | 338 | /* extract the payload */ 339 | memset(buf, '\0', buflen); 340 | p = buf; 341 | eob = buf + buflen - 1; 342 | while (rdlength > 0 && p < eob) 343 | { 344 | c = *cp++; 345 | rdlength--; 346 | while (c > 0 && p < eob) 347 | { 348 | *p++ = *cp++; 349 | c--; 350 | rdlength--; 351 | } 352 | } 353 | 354 | return ARC_STAT_OK; 355 | } 356 | 357 | /* 358 | ** ARC_GET_KEY_FILE -- retrieve a key from a text file (for testing) 359 | ** 360 | ** Parameters: 361 | ** msg -- ARC_MESSAGE handle 362 | ** buf -- buffer into which to write the result 363 | ** buflen -- bytes available at "buf" 364 | ** 365 | ** Return value: 366 | ** A ARC_STAT_* constant. 367 | ** 368 | ** Notes: 369 | ** The file opened is defined by the library option ARC_OPTS_QUERYINFO 370 | ** and must be set prior to use of this function. Failing to do 371 | ** so will cause this function to return ARC_STAT_KEYFAIL every time. 372 | ** The file should contain lines of the form: 373 | ** 374 | ** ._domainkey. key-data 375 | ** 376 | ** Case matching on the left is case-sensitive, but libopendkim already 377 | ** wraps the domain name to lowercase. 378 | */ 379 | 380 | ARC_STAT 381 | arc_get_key_file(ARC_MESSAGE *msg, u_char *buf, size_t buflen) 382 | { 383 | int n; 384 | FILE *f; 385 | u_char *p; 386 | u_char *p2; 387 | u_char *path; 388 | char name[ARC_MAXHOSTNAMELEN + 1]; 389 | 390 | assert(msg != NULL); 391 | assert(msg->arc_selector != NULL); 392 | assert(msg->arc_domain != NULL); 393 | assert(msg->arc_query == ARC_QUERY_FILE); 394 | 395 | path = msg->arc_library->arcl_queryinfo; 396 | if (path[0] == '\0') 397 | { 398 | arc_error(msg, "query file not defined"); 399 | return ARC_STAT_KEYFAIL; 400 | } 401 | 402 | f = fopen((char *) path, "r"); 403 | if (f == NULL) 404 | { 405 | arc_error(msg, "%s: fopen(): %s", path, strerror(errno)); 406 | return ARC_STAT_KEYFAIL; 407 | } 408 | 409 | n = snprintf(name, sizeof name, "%s.%s.%s", msg->arc_selector, 410 | ARC_DNSKEYNAME, msg->arc_domain); 411 | if (n == -1 || n > sizeof name) 412 | { 413 | arc_error(msg, "key query name too large"); 414 | fclose(f); 415 | return ARC_STAT_NORESOURCE; 416 | } 417 | 418 | memset(buf, '\0', buflen); 419 | while (fgets((char *) buf, buflen, f) != NULL) 420 | { 421 | if (buf[0] == '#') 422 | continue; 423 | 424 | p2 = NULL; 425 | 426 | for (p = buf; *p != '\0'; p++) 427 | { 428 | if (*p == '\n') 429 | { 430 | *p = '\0'; 431 | break; 432 | } 433 | else if (isascii(*p) && isspace(*p)) 434 | { 435 | *p = '\0'; 436 | p2 = p + 1; 437 | } 438 | else if (p2 != NULL) 439 | { 440 | break; 441 | } 442 | } 443 | 444 | if (strcasecmp((char *) name, (char *) buf) == 0 && p2 != NULL) 445 | { 446 | memmove(buf, p2, strlen(p2) + 1); 447 | fclose(f); 448 | return ARC_STAT_OK; 449 | } 450 | } 451 | 452 | fclose(f); 453 | 454 | return ARC_STAT_NOKEY; 455 | } 456 | -------------------------------------------------------------------------------- /libopenarc/arc-keys.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2005, 2007 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009, 2012, The Trusted Domain Project. All rights reserved. 6 | */ 7 | 8 | #ifndef _ARC_KEYS_H_ 9 | #define _ARC_KEYS_H_ 10 | 11 | /* libopenarc includes */ 12 | #include "arc.h" 13 | 14 | /* prototypes */ 15 | extern ARC_STAT arc_get_key_dns __P((ARC_MESSAGE *, u_char *, size_t)); 16 | extern ARC_STAT arc_get_key_file __P((ARC_MESSAGE *, u_char *, size_t)); 17 | 18 | #endif /* ! _ARC_KEYS_H_ */ 19 | -------------------------------------------------------------------------------- /libopenarc/arc-tables.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2012, 2014-2016, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #include "build-config.h" 10 | 11 | /* system includes */ 12 | #include 13 | #include 14 | #include 15 | 16 | /* libopenarc includes */ 17 | #include "arc-tables.h" 18 | #include "arc-internal.h" 19 | 20 | /* lookup tables */ 21 | static struct nametable prv_algorithms[] = /* signing algorithms */ 22 | { 23 | { "rsa-sha1", ARC_SIGN_RSASHA1 }, 24 | { "rsa-sha256", ARC_SIGN_RSASHA256 }, 25 | { NULL, -1 }, 26 | }; 27 | struct nametable *algorithms = prv_algorithms; 28 | 29 | static struct nametable prv_archdrnames[] = /* header field names:types */ 30 | { 31 | { ARC_AR_HDRNAME, ARC_KVSETTYPE_AR }, 32 | { ARC_SEAL_HDRNAME, ARC_KVSETTYPE_SEAL }, 33 | { ARC_MSGSIG_HDRNAME, ARC_KVSETTYPE_SIGNATURE }, 34 | { NULL, -1 }, 35 | }; 36 | struct nametable *archdrnames = prv_archdrnames; 37 | 38 | static struct nametable prv_canonicalizations[] = /* canonicalizations */ 39 | { 40 | { "simple", ARC_CANON_SIMPLE }, 41 | { "relaxed", ARC_CANON_RELAXED }, 42 | { NULL, -1 }, 43 | }; 44 | struct nametable *canonicalizations = prv_canonicalizations; 45 | 46 | static struct nametable prv_hashes[] = /* hashes */ 47 | { 48 | { "sha1", ARC_HASHTYPE_SHA1 }, 49 | { "sha256", ARC_HASHTYPE_SHA256 }, 50 | { NULL, -1 }, 51 | }; 52 | struct nametable *hashes = prv_hashes; 53 | 54 | static struct nametable prv_keyflags[] = /* key flags */ 55 | { 56 | { "y", ARC_KEYFLAG_TESTKEY }, 57 | { "s", ARC_KEYFLAG_NOSUBDOMAIN }, 58 | { NULL, -1 } 59 | }; 60 | struct nametable *keyflags = prv_keyflags; 61 | 62 | static struct nametable prv_keytypes[] = /* key types */ 63 | { 64 | { "rsa", ARC_KEYTYPE_RSA }, 65 | { NULL, -1 }, 66 | }; 67 | struct nametable *keytypes = prv_keytypes; 68 | 69 | static struct nametable prv_querytypes[] = /* query types */ 70 | { 71 | { "dns", ARC_QUERY_DNS }, 72 | { NULL, -1 }, 73 | }; 74 | struct nametable *querytypes = prv_querytypes; 75 | 76 | static struct nametable prv_chainstatus[] = /* chain status */ 77 | { 78 | { "none", ARC_CHAIN_NONE }, 79 | { "fail", ARC_CHAIN_FAIL }, 80 | { "pass", ARC_CHAIN_PASS }, 81 | { "unknown", ARC_CHAIN_UNKNOWN }, 82 | { NULL, -1 }, 83 | }; 84 | struct nametable *chainstatus = prv_chainstatus; 85 | 86 | static struct nametable prv_results[] = /* result codes */ 87 | { 88 | { "Success", ARC_STAT_OK }, 89 | { "Bad signature", ARC_STAT_BADSIG }, 90 | { "No signature", ARC_STAT_NOSIG }, 91 | { "No key", ARC_STAT_NOKEY }, 92 | { "Unable to verify", ARC_STAT_CANTVRFY }, 93 | { "Syntax error", ARC_STAT_SYNTAX }, 94 | { "Resource unavailable", ARC_STAT_NORESOURCE }, 95 | { "Internal error", ARC_STAT_INTERNAL }, 96 | { "Revoked key", ARC_STAT_REVOKED }, 97 | { "Invalid parameter", ARC_STAT_INVALID }, 98 | { "Not implemented", ARC_STAT_NOTIMPLEMENT }, 99 | { "Key retrieval failed", ARC_STAT_KEYFAIL }, 100 | { NULL, -1 }, 101 | }; 102 | struct nametable *results = prv_results; 103 | 104 | static struct nametable prv_settypes[] = /* set types */ 105 | { 106 | { "key", ARC_KVSETTYPE_KEY }, 107 | { "ARC signature", ARC_KVSETTYPE_SIGNATURE }, 108 | { "ARC seal", ARC_KVSETTYPE_SEAL }, 109 | { "ARC results", ARC_KVSETTYPE_AR }, 110 | { NULL, -1 }, 111 | }; 112 | struct nametable *settypes = prv_settypes; 113 | 114 | static struct nametable prv_sigerrors[] = /* signature parsing errors */ 115 | { 116 | { "no signature error", ARC_SIGERROR_OK }, 117 | { "unsupported signature version", ARC_SIGERROR_VERSION }, 118 | { "invalid domain coverage", ARC_SIGERROR_DOMAIN }, 119 | { "signature expired", ARC_SIGERROR_EXPIRED }, 120 | { "signature timestamp in the future", ARC_SIGERROR_FUTURE }, 121 | { "signature timestamp order error", ARC_SIGERROR_TIMESTAMPS }, 122 | { "invalid header canonicalization", ARC_SIGERROR_INVALID_HC }, 123 | { "invalid body canonicalization", ARC_SIGERROR_INVALID_BC }, 124 | { "signature algorithm missing", ARC_SIGERROR_MISSING_A }, 125 | { "signature algorithm invalid", ARC_SIGERROR_INVALID_A }, 126 | { "header list missing", ARC_SIGERROR_MISSING_H }, 127 | { "body length value invalid", ARC_SIGERROR_INVALID_L }, 128 | { "query method invalid", ARC_SIGERROR_INVALID_Q }, 129 | { "query option invalid", ARC_SIGERROR_INVALID_QO }, 130 | { "domain tag missing", ARC_SIGERROR_MISSING_D }, 131 | { "domain tag empty", ARC_SIGERROR_EMPTY_D }, 132 | { "selector tag missing", ARC_SIGERROR_MISSING_S }, 133 | { "selector tag empty", ARC_SIGERROR_EMPTY_S }, 134 | { "signature data missing", ARC_SIGERROR_MISSING_B }, 135 | { "signature data empty", ARC_SIGERROR_EMPTY_B }, 136 | { "signature data corrupt", ARC_SIGERROR_CORRUPT_B }, 137 | { "key not found in DNS", ARC_SIGERROR_NOKEY }, 138 | { "key DNS reply corrupt", ARC_SIGERROR_DNSSYNTAX }, 139 | { "key DNS query failed", ARC_SIGERROR_KEYFAIL }, 140 | { "body hash missing", ARC_SIGERROR_MISSING_BH }, 141 | { "body hash empty", ARC_SIGERROR_EMPTY_BH }, 142 | { "body hash corrupt", ARC_SIGERROR_CORRUPT_BH }, 143 | { "signature verification failed", ARC_SIGERROR_BADSIG }, 144 | { "unauthorized subdomain", ARC_SIGERROR_SUBDOMAIN }, 145 | { "multiple keys found", ARC_SIGERROR_MULTIREPLY }, 146 | { "header list tag empty", ARC_SIGERROR_EMPTY_H }, 147 | { "header list missing required entries", ARC_SIGERROR_INVALID_H }, 148 | { "length tag value exceeds body size", ARC_SIGERROR_TOOLARGE_L }, 149 | { "unprotected header field", ARC_SIGERROR_MBSFAILED }, 150 | { "unknown key version", ARC_SIGERROR_KEYVERSION }, 151 | { "unknown key hash", ARC_SIGERROR_KEYUNKNOWNHASH }, 152 | { "signature-key hash mismatch", ARC_SIGERROR_KEYHASHMISMATCH }, 153 | { "not an e-mail key", ARC_SIGERROR_NOTEMAILKEY }, 154 | { "key type missing", ARC_SIGERROR_KEYTYPEMISSING }, 155 | { "unknown key type", ARC_SIGERROR_KEYTYPEUNKNOWN }, 156 | { "key revoked", ARC_SIGERROR_KEYREVOKED }, 157 | { "unable to apply public key", ARC_SIGERROR_KEYDECODE }, 158 | { "version missing", ARC_SIGERROR_MISSING_V }, 159 | { "version empty", ARC_SIGERROR_EMPTY_V }, 160 | { "signing key too small", ARC_SIGERROR_KEYTOOSMALL }, 161 | { "duplicate instance", ARC_SIGERROR_DUPINSTANCE }, 162 | { NULL, -1 }, 163 | }; 164 | struct nametable *sigerrors = prv_sigerrors; 165 | 166 | /* ===================================================================== */ 167 | 168 | /* 169 | ** ARC_CODE_TO_NAME -- translate a mnemonic code to its name 170 | ** 171 | ** Parameters: 172 | ** tbl -- name table 173 | ** code -- code to translate 174 | ** 175 | ** Return value: 176 | ** Pointer to the name matching the provided code, or NULL if not found. 177 | */ 178 | 179 | const char * 180 | arc_code_to_name(struct nametable *tbl, const int code) 181 | { 182 | int c; 183 | 184 | assert(tbl != NULL); 185 | 186 | for (c = 0; ; c++) 187 | { 188 | if (tbl[c].tbl_code == -1 && tbl[c].tbl_name == NULL) 189 | return NULL; 190 | 191 | if (tbl[c].tbl_code == code) 192 | return tbl[c].tbl_name; 193 | } 194 | } 195 | 196 | /* 197 | ** ARC_NAME_TO_CODE -- translate a name to a mnemonic code 198 | ** 199 | ** Parameters: 200 | ** tbl -- name table 201 | ** name -- name to translate 202 | ** 203 | ** Return value: 204 | ** A mnemonic code matching the provided name, or -1 if not found. 205 | */ 206 | 207 | const int 208 | arc_name_to_code(struct nametable *tbl, const char *name) 209 | { 210 | int c; 211 | 212 | assert(tbl != NULL); 213 | 214 | for (c = 0; ; c++) 215 | { 216 | if (tbl[c].tbl_code == -1 && tbl[c].tbl_name == NULL) 217 | return -1; 218 | 219 | if (strcasecmp(tbl[c].tbl_name, name) == 0) 220 | return tbl[c].tbl_code; 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /libopenarc/arc-tables.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2005-2008 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009, 2010, 2012, 2014-2016, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #ifndef _ARC_TABLES_H_ 10 | #define _ARC_TABLES_H_ 11 | 12 | #ifdef __STDC__ 13 | # ifndef __P 14 | # define __P(x) x 15 | # endif /* ! __P */ 16 | #else /* __STDC__ */ 17 | # ifndef __P 18 | # define __P(x) () 19 | # endif /* ! __P */ 20 | #endif /* __STDC__ */ 21 | 22 | /* structures */ 23 | struct nametable 24 | { 25 | const char * tbl_name; /* name */ 26 | const int tbl_code; /* code */ 27 | }; 28 | 29 | /* tables */ 30 | extern struct nametable *algorithms; 31 | extern struct nametable *archdrnames; 32 | extern struct nametable *canonicalizations; 33 | extern struct nametable *chainstatus; 34 | extern struct nametable *hashes; 35 | extern struct nametable *keyflags; 36 | extern struct nametable *keytypes; 37 | extern struct nametable *settypes; 38 | extern struct nametable *sigerrors; 39 | 40 | /* prototypes */ 41 | extern const char *arc_code_to_name __P((struct nametable *tbl, 42 | const int code)); 43 | extern const int arc_name_to_code __P((struct nametable *tbl, 44 | const char *name)); 45 | 46 | #endif /* _ARC_TABLES_H_ */ 47 | -------------------------------------------------------------------------------- /libopenarc/arc-types.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, 2017, The Trusted Domain Project. All rights reserved. 3 | */ 4 | 5 | #ifndef _ARC_TYPES_H_ 6 | #define _ARC_TYPES_H_ 7 | 8 | #include "build-config.h" 9 | 10 | /* system includes */ 11 | #include 12 | #ifdef HAVE_STDBOOL_H 13 | # include 14 | #endif /* HAVE_STDBOOL_H */ 15 | #include 16 | 17 | /* OpenSSL includes */ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | /* libopenarc includes */ 25 | #include "arc.h" 26 | #include "arc-internal.h" 27 | 28 | /* struct arc_sha1 -- stuff needed to do a sha1 hash */ 29 | struct arc_sha1 30 | { 31 | int sha1_tmpfd; 32 | BIO * sha1_tmpbio; 33 | SHA_CTX sha1_ctx; 34 | u_char sha1_out[SHA_DIGEST_LENGTH]; 35 | }; 36 | 37 | #ifdef HAVE_SHA256 38 | /* struct arc_sha256 -- stuff needed to do a sha256 hash */ 39 | struct arc_sha256 40 | { 41 | int sha256_tmpfd; 42 | BIO * sha256_tmpbio; 43 | SHA256_CTX sha256_ctx; 44 | u_char sha256_out[SHA256_DIGEST_LENGTH]; 45 | }; 46 | #endif /* HAVE_SHA256 */ 47 | 48 | /* struct arc_qmethod -- signature query method */ 49 | struct arc_qmethod 50 | { 51 | char * qm_type; 52 | char * qm_options; 53 | struct arc_qmethod * qm_next; 54 | }; 55 | 56 | /* struct arc_xtag -- signature extension tag */ 57 | struct arc_xtag 58 | { 59 | char * xt_tag; 60 | char * xt_value; 61 | struct arc_xtag * xt_next; 62 | }; 63 | 64 | /* struct arc_dstring -- a dynamically-sized string */ 65 | struct arc_dstring 66 | { 67 | int ds_alloc; 68 | int ds_max; 69 | int ds_len; 70 | unsigned char * ds_buf; 71 | ARC_MESSAGE * ds_msg; 72 | }; 73 | 74 | /* struct arc_hdrfield -- a header field */ 75 | struct arc_hdrfield 76 | { 77 | uint32_t hdr_flags; 78 | size_t hdr_namelen; 79 | size_t hdr_textlen; 80 | u_char * hdr_colon; 81 | u_char * hdr_text; 82 | void * hdr_data; 83 | struct arc_hdrfield * hdr_next; 84 | }; 85 | 86 | /* hdr_flags bits */ 87 | #define ARC_HDR_SIGNED 0x01 88 | 89 | /* struct arc_set -- a complete single set of ARC header fields */ 90 | struct arc_set 91 | { 92 | struct arc_hdrfield * arcset_aar; 93 | struct arc_hdrfield * arcset_ams; 94 | struct arc_hdrfield * arcset_as; 95 | }; 96 | 97 | /* struct arc_plist -- a parameter/value pair */ 98 | struct arc_plist 99 | { 100 | u_char * plist_param; 101 | u_char * plist_value; 102 | struct arc_plist * plist_next; 103 | }; 104 | 105 | /* struct arc_kvset -- a set of parameter/value pairs */ 106 | struct arc_kvset 107 | { 108 | _Bool set_bad; 109 | arc_kvsettype_t set_type; 110 | u_char * set_data; 111 | void * set_udata; 112 | struct arc_plist * set_plist[NPRINTABLE]; 113 | struct arc_kvset * set_next; 114 | }; 115 | 116 | /* struct arc_canon -- a canonicalization status handle */ 117 | struct arc_canon 118 | { 119 | _Bool canon_done; 120 | _Bool canon_blankline; 121 | int canon_type; 122 | int canon_lastchar; 123 | int canon_bodystate; 124 | u_int canon_hashtype; 125 | u_int canon_blanks; 126 | size_t canon_hashbuflen; 127 | size_t canon_hashbufsize; 128 | ssize_t canon_remain; 129 | ssize_t canon_wrote; 130 | ssize_t canon_length; 131 | arc_canon_t canon_canon; 132 | u_char * canon_hashbuf; 133 | u_char * canon_hdrlist; 134 | void * canon_hash; 135 | struct arc_dstring * canon_buf; 136 | struct arc_hdrfield * canon_sigheader; 137 | struct arc_canon * canon_next; 138 | }; 139 | 140 | /* struct arc_msghandle -- a complete ARC transaction context */ 141 | struct arc_msghandle 142 | { 143 | _Bool arc_partial; 144 | int arc_dnssec_key; 145 | int arc_signalg; 146 | u_int arc_mode; 147 | u_int arc_nsets; 148 | u_int arc_margin; 149 | u_int arc_state; 150 | u_int arc_hdrcnt; 151 | u_int arc_timeout; 152 | u_int arc_keybits; 153 | u_int arc_keytype; 154 | u_int arc_hashtype; 155 | u_long arc_flags; 156 | arc_query_t arc_query; 157 | time_t arc_timestamp; 158 | time_t arc_sigttl; 159 | size_t arc_siglen; 160 | size_t arc_keylen; 161 | size_t arc_errorlen; 162 | size_t arc_b64keylen; 163 | ssize_t arc_bodylen; 164 | arc_canon_t arc_canonhdr; 165 | arc_canon_t arc_canonbody; 166 | ARC_CHAIN arc_cstate; 167 | ARC_SIGERROR arc_sigerror; 168 | u_char * arc_key; 169 | u_char * arc_error; 170 | u_char * arc_hdrlist; 171 | u_char * arc_domain; 172 | u_char * arc_selector; 173 | u_char * arc_authservid; 174 | u_char * arc_b64sig; 175 | u_char * arc_b64key; 176 | void * arc_signature; 177 | struct arc_qmethod * arc_querymethods; 178 | struct arc_xtag * arc_xtags; 179 | struct arc_dstring * arc_canonbuf; 180 | struct arc_dstring * arc_hdrbuf; 181 | struct arc_canon * arc_sealcanon; 182 | struct arc_canon ** arc_sealcanons; 183 | struct arc_canon * arc_valid_hdrcanon; 184 | struct arc_canon * arc_sign_hdrcanon; 185 | struct arc_canon * arc_valid_bodycanon; 186 | struct arc_canon * arc_sign_bodycanon; 187 | struct arc_canon * arc_canonhead; 188 | struct arc_canon * arc_canontail; 189 | struct arc_hdrfield * arc_hhead; 190 | struct arc_hdrfield * arc_htail; 191 | struct arc_hdrfield * arc_sealhead; 192 | struct arc_hdrfield * arc_sealtail; 193 | struct arc_kvset * arc_kvsethead; 194 | struct arc_kvset * arc_kvsettail; 195 | struct arc_set * arc_sets; 196 | ARC_LIB * arc_library; 197 | const void * arc_user_context; 198 | }; 199 | 200 | /* struct arc_lib -- a ARC library context */ 201 | struct arc_lib 202 | { 203 | _Bool arcl_signre; 204 | _Bool arcl_dnsinit_done; 205 | u_int arcl_flsize; 206 | uint32_t arcl_flags; 207 | time_t arcl_fixedtime; 208 | u_int arcl_callback_int; 209 | u_int arcl_minkeysize; 210 | u_int * arcl_flist; 211 | struct arc_dstring * arcl_sslerrbuf; 212 | u_char ** arcl_oversignhdrs; 213 | void (*arcl_dns_callback) (const void *context); 214 | void *arcl_dns_service; 215 | int (*arcl_dns_init) (void **srv); 216 | void (*arcl_dns_close) (void *srv); 217 | int (*arcl_dns_start) (void *srv, int type, 218 | unsigned char *query, 219 | unsigned char *buf, 220 | size_t buflen, 221 | void **qh); 222 | int (*arcl_dns_cancel) (void *srv, void *qh); 223 | int (*arcl_dns_waitreply) (void *srv, 224 | void *qh, 225 | struct timeval *to, 226 | size_t *bytes, 227 | int *error, 228 | int *dnssec); 229 | regex_t arcl_hdrre; 230 | u_char arcl_tmpdir[MAXPATHLEN + 1]; 231 | u_char arcl_queryinfo[MAXPATHLEN + 1]; 232 | }; 233 | 234 | #endif /* _ARC_TYPES_H_ */ 235 | -------------------------------------------------------------------------------- /libopenarc/arc-util.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, 2017, The Trusted Domain Project. All rights reserved. 3 | */ 4 | 5 | #ifndef _ARC_UTIL_H_ 6 | #define _ARC_UTIL_H_ 7 | 8 | #include "build-config.h" 9 | 10 | /* system includes */ 11 | #include 12 | #include 13 | #ifdef HAVE_STDBOOL_H 14 | # include 15 | #endif /* HAVE_STDBOOL_H */ 16 | 17 | /* libopenarc includes */ 18 | #include "arc.h" 19 | 20 | extern void arc_dstring_blank __P((struct arc_dstring *)); 21 | extern _Bool arc_dstring_cat __P((struct arc_dstring *, u_char *)); 22 | extern _Bool arc_dstring_cat1 __P((struct arc_dstring *, int)); 23 | extern _Bool arc_dstring_catn __P((struct arc_dstring *, u_char *, size_t)); 24 | extern _Bool arc_dstring_copy __P((struct arc_dstring *, u_char *)); 25 | extern void arc_dstring_free __P((struct arc_dstring *)); 26 | extern u_char *arc_dstring_get __P((struct arc_dstring *)); 27 | extern int arc_dstring_len __P((struct arc_dstring *)); 28 | extern struct arc_dstring *arc_dstring_new __P((ARC_MESSAGE *, int, int)); 29 | extern size_t arc_dstring_printf __P((struct arc_dstring *dstr, char *fmt, 30 | ...)); 31 | 32 | extern int arc_check_dns_reply __P((unsigned char *ansbuf, size_t anslen, 33 | int xclass, int xtype)); 34 | 35 | extern void arc_clobber_array __P((char **)); 36 | extern void arc_collapse __P((u_char *)); 37 | extern const char **arc_copy_array __P((char **)); 38 | extern void arc_lowerhdr __P((u_char *)); 39 | extern u_char *arc_strndup(u_char *, size_t); 40 | 41 | extern _Bool arc_hdrlist __P((u_char *, size_t, u_char **, _Bool)); 42 | 43 | extern void arc_min_timeval __P((struct timeval *, struct timeval *, 44 | struct timeval *, struct timeval **)); 45 | 46 | extern ARC_STAT arc_tmpfile __P((ARC_MESSAGE *, int *, _Bool)); 47 | 48 | #endif /* _ARC_UTIL_H_ */ 49 | -------------------------------------------------------------------------------- /libopenarc/arc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, 2017, The Trusted Domain Project. All rights reserved. 3 | */ 4 | 5 | #ifndef _ARC_H_ 6 | #define _ARC_H_ 7 | 8 | #ifdef __cplusplus 9 | extern "C" { 10 | #endif /* __cplusplus */ 11 | 12 | /* system includes */ 13 | #include 14 | #include 15 | #include 16 | #ifdef HAVE_STDBOOL_H 17 | # include 18 | #endif /* HAVE_STDBOOL_H */ 19 | #include 20 | #ifdef HAVE_LIMITS_H 21 | # include 22 | #endif /* HAVE_LIMITS_H */ 23 | 24 | /* 25 | ** version -- 0xrrMMmmpp 26 | ** 27 | ** rr == release number 28 | ** MM == major revision number 29 | ** mm == minor revision number 30 | ** pp == patch number 31 | */ 32 | 33 | #define OPENARC_LIB_VERSION 0x00010000 34 | 35 | #ifdef __STDC__ 36 | # ifndef __P 37 | # define __P(x) x 38 | # endif /* ! __P */ 39 | #else /* __STDC__ */ 40 | # ifndef __P 41 | # define __P(x) () 42 | # endif /* ! __P */ 43 | #endif /* __STDC__ */ 44 | 45 | /* definitions */ 46 | #define ARC_HDRMARGIN 75 /* "standard" header margin */ 47 | #define ARC_MAXHEADER 4096 /* buffer for caching one header */ 48 | #define ARC_MAXHOSTNAMELEN 256 /* max. FQDN we support */ 49 | 50 | #define ARC_AR_HDRNAME "ARC-Authentication-Results" 51 | #define ARC_DEFAULT_MINKEYSIZE 1024 52 | #define ARC_MSGSIG_HDRNAME "ARC-Message-Signature" 53 | #define ARC_MSGSIG_HDRNAMELEN sizeof(ARC_MSGSIG_HDRNAME) - 1 54 | #define ARC_SEAL_HDRNAME "ARC-Seal" 55 | #define ARC_SEAL_HDRNAMELEN sizeof(ARC_SEAL_HDRNAME) - 1 56 | 57 | #define ARC_EXT_AR_HDRNAME "Authentication-Results" 58 | 59 | /* special DNS tokens */ 60 | #define ARC_DNSKEYNAME "_domainkey" 61 | 62 | #define DKIM_VERSION_KEY "DKIM1" 63 | 64 | /* 65 | ** ARC_STAT -- status code type 66 | */ 67 | 68 | typedef int ARC_STAT; 69 | 70 | #define ARC_STAT_OK 0 /* function completed successfully */ 71 | #define ARC_STAT_BADSIG 1 /* signature available but failed */ 72 | #define ARC_STAT_NOSIG 2 /* no signature available */ 73 | #define ARC_STAT_NOKEY 3 /* public key not found */ 74 | #define ARC_STAT_CANTVRFY 4 /* can't get domain key to verify */ 75 | #define ARC_STAT_SYNTAX 5 /* message is not valid syntax */ 76 | #define ARC_STAT_NORESOURCE 6 /* resource unavailable */ 77 | #define ARC_STAT_INTERNAL 7 /* internal error */ 78 | #define ARC_STAT_REVOKED 8 /* key found, but revoked */ 79 | #define ARC_STAT_INVALID 9 /* invalid function parameter */ 80 | #define ARC_STAT_NOTIMPLEMENT 10 /* function not implemented */ 81 | #define ARC_STAT_KEYFAIL 11 /* key retrieval failed */ 82 | #define ARC_STAT_MULTIDNSREPLY 12 /* multiple DNS replies */ 83 | #define ARC_STAT_SIGGEN 13 /* seal generation failed */ 84 | 85 | /* 86 | ** ARC_CHAIN -- chain state 87 | */ 88 | 89 | typedef int ARC_CHAIN; 90 | 91 | #define ARC_CHAIN_UNKNOWN (-1) /* unknown */ 92 | #define ARC_CHAIN_NONE 0 /* none */ 93 | #define ARC_CHAIN_FAIL 1 /* fail */ 94 | #define ARC_CHAIN_PASS 2 /* pass */ 95 | 96 | /* 97 | ** ARC_CANON_T -- a canoncalization mode 98 | */ 99 | 100 | typedef int arc_canon_t; 101 | 102 | #define ARC_CANON_UNKNOWN (-1) 103 | #define ARC_CANON_SIMPLE 0 104 | #define ARC_CANON_RELAXED 1 105 | 106 | /* 107 | ** ARC_SIGERROR -- signature errors 108 | */ 109 | 110 | typedef int ARC_SIGERROR; 111 | 112 | #define ARC_SIGERROR_UNKNOWN (-1) /* unknown error */ 113 | #define ARC_SIGERROR_OK 0 /* no error */ 114 | #define ARC_SIGERROR_VERSION 1 /* unsupported version */ 115 | #define ARC_SIGERROR_DOMAIN 2 /* invalid domain (d=/i=) */ 116 | #define ARC_SIGERROR_EXPIRED 3 /* signature expired */ 117 | #define ARC_SIGERROR_FUTURE 4 /* signature in the future */ 118 | #define ARC_SIGERROR_TIMESTAMPS 5 /* x= < t= */ 119 | #define ARC_SIGERROR_UNUSED 6 /* OBSOLETE */ 120 | #define ARC_SIGERROR_INVALID_HC 7 /* c= invalid (header) */ 121 | #define ARC_SIGERROR_INVALID_BC 8 /* c= invalid (body) */ 122 | #define ARC_SIGERROR_MISSING_A 9 /* a= missing */ 123 | #define ARC_SIGERROR_INVALID_A 10 /* a= invalid */ 124 | #define ARC_SIGERROR_MISSING_H 11 /* h= missing */ 125 | #define ARC_SIGERROR_INVALID_L 12 /* l= invalid */ 126 | #define ARC_SIGERROR_INVALID_Q 13 /* q= invalid */ 127 | #define ARC_SIGERROR_INVALID_QO 14 /* q= option invalid */ 128 | #define ARC_SIGERROR_MISSING_D 15 /* d= missing */ 129 | #define ARC_SIGERROR_EMPTY_D 16 /* d= empty */ 130 | #define ARC_SIGERROR_MISSING_S 17 /* s= missing */ 131 | #define ARC_SIGERROR_EMPTY_S 18 /* s= empty */ 132 | #define ARC_SIGERROR_MISSING_B 19 /* b= missing */ 133 | #define ARC_SIGERROR_EMPTY_B 20 /* b= empty */ 134 | #define ARC_SIGERROR_CORRUPT_B 21 /* b= corrupt */ 135 | #define ARC_SIGERROR_NOKEY 22 /* no key found in DNS */ 136 | #define ARC_SIGERROR_DNSSYNTAX 23 /* DNS reply corrupt */ 137 | #define ARC_SIGERROR_KEYFAIL 24 /* DNS query failed */ 138 | #define ARC_SIGERROR_MISSING_BH 25 /* bh= missing */ 139 | #define ARC_SIGERROR_EMPTY_BH 26 /* bh= empty */ 140 | #define ARC_SIGERROR_CORRUPT_BH 27 /* bh= corrupt */ 141 | #define ARC_SIGERROR_BADSIG 28 /* signature mismatch */ 142 | #define ARC_SIGERROR_SUBDOMAIN 29 /* unauthorized subdomain */ 143 | #define ARC_SIGERROR_MULTIREPLY 30 /* multiple records returned */ 144 | #define ARC_SIGERROR_EMPTY_H 31 /* h= empty */ 145 | #define ARC_SIGERROR_INVALID_H 32 /* h= missing req'd entries */ 146 | #define ARC_SIGERROR_TOOLARGE_L 33 /* l= value exceeds body size */ 147 | #define ARC_SIGERROR_MBSFAILED 34 /* "must be signed" failure */ 148 | #define ARC_SIGERROR_KEYVERSION 35 /* unknown key version */ 149 | #define ARC_SIGERROR_KEYUNKNOWNHASH 36 /* unknown key hash */ 150 | #define ARC_SIGERROR_KEYHASHMISMATCH 37 /* sig-key hash mismatch */ 151 | #define ARC_SIGERROR_NOTEMAILKEY 38 /* not an e-mail key */ 152 | #define ARC_SIGERROR_UNUSED2 39 /* OBSOLETE */ 153 | #define ARC_SIGERROR_KEYTYPEMISSING 40 /* key type missing */ 154 | #define ARC_SIGERROR_KEYTYPEUNKNOWN 41 /* key type unknown */ 155 | #define ARC_SIGERROR_KEYREVOKED 42 /* key revoked */ 156 | #define ARC_SIGERROR_KEYDECODE 43 /* key couldn't be decoded */ 157 | #define ARC_SIGERROR_MISSING_V 44 /* v= tag missing */ 158 | #define ARC_SIGERROR_EMPTY_V 45 /* v= tag empty */ 159 | #define ARC_SIGERROR_KEYTOOSMALL 46 /* too few key bits */ 160 | #define ARC_SIGERROR_DUPINSTANCE 47 /* duplicate instance */ 161 | 162 | /* generic DNS error codes */ 163 | #define ARC_DNS_ERROR (-1) /* error in transit */ 164 | #define ARC_DNS_SUCCESS 0 /* reply available */ 165 | #define ARC_DNS_NOREPLY 1 /* reply not available (yet) */ 166 | #define ARC_DNS_EXPIRED 2 /* no reply, query expired */ 167 | #define ARC_DNS_INVALID 3 /* invalid request */ 168 | 169 | /* 170 | ** ARC_SIGN -- signing method 171 | */ 172 | 173 | typedef int arc_alg_t; 174 | 175 | #define ARC_SIGN_UNKNOWN (-2) /* unknown method */ 176 | #define ARC_SIGN_DEFAULT (-1) /* use internal default */ 177 | #define ARC_SIGN_RSASHA1 0 /* an RSA-signed SHA1 digest */ 178 | #define ARC_SIGN_RSASHA256 1 /* an RSA-signed SHA256 digest */ 179 | 180 | /* 181 | ** ARC_QUERY -- key query method 182 | */ 183 | 184 | typedef int arc_query_t; 185 | 186 | #define ARC_QUERY_UNKNOWN (-1) /* unknown method */ 187 | #define ARC_QUERY_DNS 0 /* DNS query method (per the draft) */ 188 | #define ARC_QUERY_FILE 1 /* text file method (for testing) */ 189 | 190 | #define ARC_QUERY_DEFAULT ARC_QUERY_DNS 191 | 192 | /* 193 | ** ARC_PARAM -- known signature parameters 194 | */ 195 | 196 | typedef int arc_param_t; 197 | 198 | #define ARC_PARAM_UNKNOWN (-1) /* unknown */ 199 | #define ARC_PARAM_SIGNATURE 0 /* b */ 200 | #define ARC_PARAM_SIGNALG 1 /* a */ 201 | #define ARC_PARAM_DOMAIN 2 /* d */ 202 | #define ARC_PARAM_SELECTOR 5 /* s */ 203 | #define ARC_PARAM_VERSION 7 /* v */ 204 | #define ARC_PARAM_INSTANCE 8 /* i */ 205 | #define ARC_PARAM_TIMESTAMP 9 /* t */ 206 | #define ARC_PARAM_CHAINSTATUS 10 /* cv */ 207 | #define ARC_PARAM_KEYPATH 11 /* k */ 208 | 209 | /* 210 | ** ARC_OPTS -- library-specific options 211 | */ 212 | 213 | typedef int arc_opt_t; 214 | 215 | /* what operations can be done */ 216 | #define ARC_OP_GETOPT 0 217 | #define ARC_OP_SETOPT 1 218 | 219 | typedef int arc_opts_t; 220 | 221 | /* what options can be set */ 222 | #define ARC_OPTS_FLAGS 0 223 | #define ARC_OPTS_TMPDIR 1 224 | #define ARC_OPTS_FIXEDTIME 2 225 | #define ARC_OPTS_SIGNHDRS 3 226 | #define ARC_OPTS_OVERSIGNHDRS 4 227 | #define ARC_OPTS_MINKEYSIZE 5 228 | 229 | /* flags */ 230 | #define ARC_LIBFLAGS_NONE 0x00000000 231 | #define ARC_LIBFLAGS_FIXCRLF 0x00000001 232 | #define ARC_LIBFLAGS_KEEPFILES 0x00000002 233 | 234 | /* default */ 235 | #define ARC_LIBFLAGS_DEFAULT ARC_LIBFLAGS_NONE 236 | 237 | /* 238 | ** ARC_DNSSEC -- results of DNSSEC queries 239 | */ 240 | 241 | #define ARC_DNSSEC_UNKNOWN (-1) 242 | #define ARC_DNSSEC_BOGUS 0 243 | #define ARC_DNSSEC_INSECURE 1 244 | #define ARC_DNSSEC_SECURE 2 245 | 246 | /* 247 | ** ARC_KEYFLAG -- key flags 248 | */ 249 | 250 | #define ARC_KEYFLAG_TESTKEY 0x01 251 | #define ARC_KEYFLAG_NOSUBDOMAIN 0x02 252 | 253 | /* 254 | ** ARC_MODE -- operating modes 255 | */ 256 | 257 | typedef u_int arc_mode_t; 258 | 259 | #define ARC_MODE_SIGN 0x01 260 | #define ARC_MODE_VERIFY 0x02 261 | 262 | /* 263 | ** ARC_LIB -- library handle 264 | */ 265 | 266 | struct arc_lib; 267 | typedef struct arc_lib ARC_LIB; 268 | 269 | /* LIBRARY FEATURES */ 270 | #define ARC_FEATURE_SHA256 1 271 | 272 | #define ARC_FEATURE_MAX 1 273 | 274 | extern _Bool arc_libfeature __P((ARC_LIB *lib, u_int fc)); 275 | 276 | /* 277 | ** ARC_MESSAGE -- ARC message context 278 | */ 279 | 280 | struct arc_msghandle; 281 | typedef struct arc_msghandle ARC_MESSAGE; 282 | 283 | /* 284 | ** ARC_HDRFIELD -- a header field 285 | */ 286 | 287 | struct arc_hdrfield; 288 | typedef struct arc_hdrfield ARC_HDRFIELD; 289 | 290 | /* 291 | ** PROTOTYPES 292 | */ 293 | 294 | /* 295 | ** ARC_ERROR -- log an error message to an ARC message context 296 | ** 297 | ** Parameters: 298 | ** msg -- ARC message context 299 | ** fmt -- format 300 | ** ... -- arguments 301 | ** 302 | ** Return value: 303 | ** None. 304 | */ 305 | 306 | extern void arc_error __P((ARC_MESSAGE *, const char *, ...)); 307 | 308 | /* 309 | ** ARC_INIT -- create a library instance 310 | ** 311 | ** Parameters: 312 | ** None. 313 | ** 314 | ** Return value: 315 | ** A new library instance. 316 | */ 317 | 318 | extern ARC_LIB *arc_init __P((void)); 319 | 320 | /* 321 | ** ARC_CLOSE -- terminate a library instance 322 | ** 323 | ** Parameters: 324 | ** lib -- library instance to terminate 325 | ** 326 | ** Return value: 327 | ** None. 328 | */ 329 | 330 | extern void arc_close __P((ARC_LIB *)); 331 | 332 | /* 333 | ** ARC_GETERROR -- return any stored error string from within the DKIM 334 | ** context handle 335 | ** 336 | ** Parameters: 337 | ** msg -- ARC_MESSAGE handle from which to retrieve an error string 338 | ** 339 | ** Return value: 340 | ** A pointer to the stored string, or NULL if none was stored. 341 | */ 342 | 343 | extern const char *arc_geterror __P((ARC_MESSAGE *)); 344 | 345 | /* 346 | ** 347 | ** ARC_OPTIONS -- get/set library options 348 | ** 349 | ** Parameters: 350 | ** lib -- library instance of interest 351 | ** opt -- ARC_OP_GETOPT or ARC_OP_SETOPT 352 | ** arg -- ARC_OPTS_* constant 353 | ** val -- pointer to the new new value (or NULL) 354 | ** valsz -- size of the thing at val 355 | ** 356 | ** Return value: 357 | ** An ARC_STAT_* constant. 358 | ** argument. 359 | */ 360 | 361 | extern ARC_STAT arc_options __P((ARC_LIB *, int, int, void *, size_t)); 362 | 363 | /* 364 | ** ARC_GETSSLBUF -- retrieve SSL error buffer 365 | ** 366 | ** Parameters: 367 | ** lib -- library handle 368 | ** 369 | ** Return value: 370 | ** Pointer to the SSL buffer in the library handle. 371 | */ 372 | 373 | extern const char *arc_getsslbuf __P((ARC_LIB *)); 374 | 375 | /* 376 | ** ARC_MESSAGE -- create a new message handle 377 | ** 378 | ** Parameters: 379 | ** lib -- containing library instance 380 | ** canonhdr -- canonicalization to use for the header 381 | ** canonbody -- canonicalization to use for the body 382 | ** signalg -- signing algorithm 383 | ** mode -- mask of mode bits 384 | ** err -- error string (returned) 385 | ** 386 | ** Return value: 387 | ** A new message instance, or NULL on failure (and "err" is updated). 388 | */ 389 | 390 | extern ARC_MESSAGE *arc_message __P((ARC_LIB *, arc_canon_t, arc_canon_t, 391 | arc_alg_t, arc_mode_t, const u_char **)); 392 | 393 | /* 394 | ** ARC_FREE -- deallocate a message object 395 | ** 396 | ** Parameters: 397 | ** msg -- message object to be destroyed 398 | ** 399 | ** Return value: 400 | ** None. 401 | */ 402 | 403 | extern void arc_free __P((ARC_MESSAGE *)); 404 | 405 | /* 406 | ** ARC_HEADER_FIELD -- consume a header field 407 | ** 408 | ** Parameters: 409 | ** msg -- message handle 410 | ** hname -- name of the header field 411 | ** hlen -- bytes to use at hname 412 | ** 413 | ** Return value: 414 | ** An ARC_STAT_* constant. 415 | */ 416 | 417 | extern ARC_STAT arc_header_field __P((ARC_MESSAGE *, u_char *, size_t)); 418 | 419 | /* 420 | ** ARC_EOH -- declare no more headers are coming 421 | ** 422 | ** Parameters: 423 | ** msg -- message handle 424 | ** 425 | ** Return value: 426 | ** An ARC_STAT_* constant. 427 | ** 428 | ** Notes: 429 | ** This can probably be merged with arc_eom(). 430 | */ 431 | 432 | extern ARC_STAT arc_eoh __P((ARC_MESSAGE *)); 433 | 434 | /* 435 | ** ARC_BODY -- process a body chunk 436 | ** 437 | ** Parameters: 438 | ** msg -- an ARC message handle 439 | ** buf -- the body chunk to be processed, in canonical format 440 | ** len -- number of bytes to process starting at "buf" 441 | ** 442 | ** Return value: 443 | ** A ARC_STAT_* constant. 444 | */ 445 | 446 | extern ARC_STAT arc_body __P((ARC_MESSAGE *msg, u_char *buf, size_t len)); 447 | 448 | /* 449 | ** ARC_EOM -- declare end of message 450 | ** 451 | ** Parameters: 452 | ** msg -- message handle 453 | ** 454 | ** Return value: 455 | ** An ARC_STAT_* constant. 456 | */ 457 | 458 | extern ARC_STAT arc_eom __P((ARC_MESSAGE *)); 459 | 460 | /* 461 | ** ARC_SET_CV -- force the chain state 462 | ** 463 | ** Parameters: 464 | ** msg -- ARC_MESSAGE object 465 | ** cv -- chain state 466 | */ 467 | 468 | extern void arc_set_cv(ARC_MESSAGE *, ARC_CHAIN); 469 | 470 | /* 471 | ** ARC_GETSEAL -- get the "seal" to apply to this message 472 | ** 473 | ** Parameters: 474 | ** msg -- ARC_MESSAGE object 475 | ** seal -- seal to apply (returned) 476 | ** authservid -- authservid to use when generating A-R fields 477 | ** selector -- selector name 478 | ** domain -- domain name 479 | ** key -- secret key 480 | ** keylen -- key length 481 | ** ar -- Authentication-Results to be enshrined 482 | ** 483 | ** Return value: 484 | ** An ARC_STAT_* constant. 485 | ** 486 | ** Notes: 487 | ** The "seal" is a sequence of prepared header fields that should be 488 | ** prepended to the message in the presented order. 489 | */ 490 | 491 | extern ARC_STAT arc_getseal __P((ARC_MESSAGE *, ARC_HDRFIELD **, char *, 492 | char *, char *, u_char *, size_t, u_char *)); 493 | 494 | /* 495 | ** ARC_HDR_NAME -- extract name from an ARC_HDRFIELD 496 | ** 497 | ** Parameters: 498 | ** hdr -- ARC_HDRFIELD object 499 | ** len -- length of the header field name (returned) 500 | ** 501 | ** Return value: 502 | ** Header field name stored in the object. 503 | */ 504 | 505 | extern u_char *arc_hdr_name __P((ARC_HDRFIELD *, size_t *)); 506 | 507 | /* 508 | ** ARC_HDR_VALUE -- extract value from an ARC_HDRFIELD 509 | ** 510 | ** Parameters: 511 | ** hdr -- ARC_HDRFIELD object 512 | ** 513 | ** Return value: 514 | ** Header field value stored in the object. 515 | */ 516 | 517 | extern u_char *arc_hdr_value __P((ARC_HDRFIELD *)); 518 | 519 | /* 520 | ** ARC_HDR_NEXT -- return pointer to next ARC_HDRFIELD 521 | ** 522 | ** Parameters: 523 | ** hdr -- ARC_HDRFIELD object 524 | ** 525 | ** Return value: 526 | ** Pointer to the next ARC_HDRFIELD in the sequence. 527 | */ 528 | 529 | extern ARC_HDRFIELD *arc_hdr_next __P((ARC_HDRFIELD *hdr)); 530 | 531 | /* 532 | ** ARC_SSL_VERSION -- report the version of the crypto library against which 533 | ** the library was compiled, so the caller can ensure it matches 534 | ** 535 | ** Parameters: 536 | ** None. 537 | ** 538 | ** Return value: 539 | ** SSL library version, expressed as a uint64_t. 540 | */ 541 | 542 | extern uint64_t arc_ssl_version __P((void)); 543 | 544 | /* 545 | ** ARC_GET_DOMAIN -- retrieve stored domain for this message 546 | ** 547 | ** Parameters: 548 | ** msg -- ARC_MESSAGE object 549 | ** 550 | ** Return value: 551 | ** Pointer to string containing the domain stored for this message 552 | */ 553 | 554 | extern char *arc_get_domain __P((ARC_MESSAGE *msg)); 555 | 556 | /* 557 | ** ARC_CHAIN_STR -- retrieve chain status, as a string 558 | ** 559 | ** Parameters: 560 | ** msg -- ARC_MESSAGE object 561 | ** 562 | ** Return value: 563 | ** Pointer to string containing the current chain status. 564 | */ 565 | 566 | extern const char *arc_chain_str __P((ARC_MESSAGE *msg)); 567 | 568 | #ifdef __cplusplus 569 | } 570 | #endif /* __cplusplus */ 571 | 572 | #endif /* _ARC_H_ */ 573 | -------------------------------------------------------------------------------- /libopenarc/base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, The Trusted Domain Project. All rights reserved. 3 | */ 4 | 5 | /* system includes */ 6 | #include 7 | #include 8 | 9 | /* libopendkim includes */ 10 | #include "base64.h" 11 | 12 | /* base64 alphabet */ 13 | static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 14 | 15 | /* base64 decode stuff */ 16 | static int decoder[256] = 17 | { 18 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 20 | 0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0, 21 | 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 22 | 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0, 23 | 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 24 | 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, 25 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 26 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 29 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 31 | }; 32 | 33 | #ifndef NULL 34 | # define NULL 0 35 | #endif /* ! NULL */ 36 | 37 | /* 38 | ** ARC_BASE64_DECODE -- decode a base64 blob 39 | ** 40 | ** Parameters: 41 | ** str -- string to decide 42 | ** buf -- where to write it 43 | ** buflen -- bytes available at "buf" 44 | ** 45 | ** Return value: 46 | ** >= 0 -- success; length of what was decoded is returned 47 | ** -1 -- corrupt 48 | ** -2 -- not enough space at "buf" 49 | */ 50 | 51 | int 52 | arc_base64_decode(u_char *str, u_char *buf, size_t buflen) 53 | { 54 | int n = 0; 55 | int bits = 0; 56 | int char_count = 0; 57 | u_char *c; 58 | 59 | assert(str != NULL); 60 | assert(buf != NULL); 61 | 62 | for (c = str; *c != '=' && *c != '\0'; c++) 63 | { 64 | /* end padding */ 65 | if (*c == '=' || *c == '\0') 66 | break; 67 | 68 | /* skip stuff not part of the base64 alphabet (RFC2045) */ 69 | if (!((*c >= 'A' && *c <= 'Z') || 70 | (*c >= 'a' && *c <= 'z') || 71 | (*c >= '0' && *c <= '9') || 72 | (*c == '+') || 73 | (*c == '/'))) 74 | continue; 75 | 76 | /* everything else gets decoded */ 77 | bits += decoder[(int) *c]; 78 | char_count++; 79 | if (n + 3 > buflen) 80 | return -2; 81 | if (char_count == 4) 82 | { 83 | buf[n++] = (bits >> 16); 84 | buf[n++] = ((bits >> 8) & 0xff); 85 | buf[n++] = (bits & 0xff); 86 | bits = 0; 87 | char_count = 0; 88 | } 89 | else 90 | { 91 | bits <<= 6; 92 | } 93 | } 94 | 95 | /* XXX -- don't bother checking for proper termination (for now) */ 96 | 97 | /* process trailing data, if any */ 98 | switch (char_count) 99 | { 100 | case 0: 101 | break; 102 | 103 | case 1: 104 | /* base64 decoding incomplete; at least two bits missing */ 105 | return -1; 106 | 107 | case 2: 108 | if (n + 1 > buflen) 109 | return -2; 110 | buf[n++] = (bits >> 10); 111 | break; 112 | 113 | case 3: 114 | if (n + 2 > buflen) 115 | return -2; 116 | buf[n++] = (bits >> 16); 117 | buf[n++] = ((bits >> 8) & 0xff); 118 | break; 119 | } 120 | 121 | return n; 122 | } 123 | 124 | /* 125 | ** ARC_BASE64_ENCODE -- encode base64 data 126 | ** 127 | ** Parameters: 128 | ** data -- data to encode 129 | ** datalen -- bytes at "data" to encode 130 | ** buf -- where to write the encoding 131 | ** buflen -- bytes available at "buf" 132 | ** 133 | ** Return value: 134 | ** >= 0 -- success; number of bytes written to "buf" returned 135 | ** -1 -- failure (not enough space at "buf") 136 | */ 137 | 138 | int 139 | arc_base64_encode(u_char *data, size_t datalen, u_char *buf, size_t buflen) 140 | { 141 | int bits; 142 | int c; 143 | int char_count; 144 | size_t n; 145 | 146 | assert(data != NULL); 147 | assert(buf != NULL); 148 | 149 | bits = 0; 150 | char_count = 0; 151 | n = 0; 152 | 153 | for (c = 0; c < datalen; c++) 154 | { 155 | bits += data[c]; 156 | char_count++; 157 | if (char_count == 3) 158 | { 159 | if (n + 4 > buflen) 160 | return -1; 161 | 162 | buf[n++] = alphabet[bits >> 18]; 163 | buf[n++] = alphabet[(bits >> 12) & 0x3f]; 164 | buf[n++] = alphabet[(bits >> 6) & 0x3f]; 165 | buf[n++] = alphabet[bits & 0x3f]; 166 | bits = 0; 167 | char_count = 0; 168 | } 169 | else 170 | { 171 | bits <<= 8; 172 | } 173 | } 174 | 175 | if (char_count != 0) 176 | { 177 | if (n + 4 > buflen) 178 | return -1; 179 | 180 | bits <<= 16 - (8 * char_count); 181 | buf[n++] = alphabet[bits >> 18]; 182 | buf[n++] = alphabet[(bits >> 12) & 0x3f]; 183 | if (char_count == 1) 184 | { 185 | buf[n++] = '='; 186 | buf[n++] = '='; 187 | } 188 | else 189 | { 190 | buf[n++] = alphabet[(bits >> 6) & 0x3f]; 191 | buf[n++] = '='; 192 | } 193 | } 194 | 195 | return n; 196 | } 197 | -------------------------------------------------------------------------------- /libopenarc/base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, The Trusted Domain Project. All rights reserved. 3 | */ 4 | 5 | #ifndef _BASE64_H_ 6 | #define _BASE64_H_ 7 | 8 | /* system includes */ 9 | #include 10 | 11 | /* prototypes */ 12 | extern int arc_base64_decode(u_char *str, u_char *buf, size_t buflen); 13 | extern int arc_base64_encode(u_char *data, size_t datalen, u_char *buf, 14 | size_t buflen); 15 | 16 | #endif /* ! _BASE64_H_ */ 17 | -------------------------------------------------------------------------------- /libopenarc/docs/Makefile.am: -------------------------------------------------------------------------------- 1 | dist_doc_DATA = index.html 2 | -------------------------------------------------------------------------------- /libopenarc/docs/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trusteddomainproject/OpenARC/355ee2a1ca85acccce494478991983b54f794f4e/libopenarc/docs/index.html -------------------------------------------------------------------------------- /libopenarc/openarc.pc.in: -------------------------------------------------------------------------------- 1 | # Process this file with autoconf to produce a pkg-config metadata file. 2 | 3 | prefix=@prefix@ 4 | exec_prefix=@exec_prefix@ 5 | libdir=@libdir@ 6 | includedir=@includedir@/openarc 7 | 8 | Name: OpenARC Library 9 | Description: Library for performing ARC signing and verification 10 | URL: http://trusteddomain.org/openarc 11 | Version: @VERSION@ 12 | Libs: -L${libdir} @PTHREAD_CFLAGS@ -lopenarc 13 | Libs.private: @LIBOPENARC_LIBS_PKG@ @PTHREAD_LIBS@ 14 | Cflags: -I${includedir} @PTHREAD_CFLAGS@ 15 | 16 | -------------------------------------------------------------------------------- /libopenarc/tests/Makefile.am: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trusteddomainproject/OpenARC/355ee2a1ca85acccce494478991983b54f794f4e/libopenarc/tests/Makefile.am -------------------------------------------------------------------------------- /m4/.gitignore: -------------------------------------------------------------------------------- 1 | libtool.m4 2 | ltoptions.m4 3 | ltsugar.m4 4 | ltversion.m4 5 | lt~obsolete.m4 6 | -------------------------------------------------------------------------------- /m4/ac_pthread.m4: -------------------------------------------------------------------------------- 1 | # =========================================================================== 2 | # http://www.gnu.org/software/autoconf-archive/ax_pthread.html 3 | # =========================================================================== 4 | # 5 | # SYNOPSIS 6 | # 7 | # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) 8 | # 9 | # DESCRIPTION 10 | # 11 | # This macro figures out how to build C programs using POSIX threads. It 12 | # sets the PTHREAD_LIBS output variable to the threads library and linker 13 | # flags, and the PTHREAD_CFLAGS output variable to any special C compiler 14 | # flags that are needed. (The user can also force certain compiler 15 | # flags/libs to be tested by setting these environment variables.) 16 | # 17 | # Also sets PTHREAD_CC to any special C compiler that is needed for 18 | # multi-threaded programs (defaults to the value of CC otherwise). (This 19 | # is necessary on AIX to use the special cc_r compiler alias.) 20 | # 21 | # NOTE: You are assumed to not only compile your program with these flags, 22 | # but also link it with them as well. e.g. you should link with 23 | # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS 24 | # 25 | # If you are only building threads programs, you may wish to use these 26 | # variables in your default LIBS, CFLAGS, and CC: 27 | # 28 | # LIBS="$PTHREAD_LIBS $LIBS" 29 | # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 30 | # CC="$PTHREAD_CC" 31 | # 32 | # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant 33 | # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name 34 | # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). 35 | # 36 | # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the 37 | # PTHREAD_PRIO_INHERIT symbol is defined when compiling with 38 | # PTHREAD_CFLAGS. 39 | # 40 | # ACTION-IF-FOUND is a list of shell commands to run if a threads library 41 | # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it 42 | # is not found. If ACTION-IF-FOUND is not specified, the default action 43 | # will define HAVE_PTHREAD. 44 | # 45 | # Please let the authors know if this macro fails on any platform, or if 46 | # you have any other suggestions or comments. This macro was based on work 47 | # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help 48 | # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by 49 | # Alejandro Forero Cuervo to the autoconf macro repository. We are also 50 | # grateful for the helpful feedback of numerous users. 51 | # 52 | # Updated for Autoconf 2.68 by Daniel Richard G. 53 | # 54 | # LICENSE 55 | # 56 | # Copyright (c) 2008 Steven G. Johnson 57 | # Copyright (c) 2011 Daniel Richard G. 58 | # 59 | # This program is free software: you can redistribute it and/or modify it 60 | # under the terms of the GNU General Public License as published by the 61 | # Free Software Foundation, either version 3 of the License, or (at your 62 | # option) any later version. 63 | # 64 | # This program is distributed in the hope that it will be useful, but 65 | # WITHOUT ANY WARRANTY; without even the implied warranty of 66 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 67 | # Public License for more details. 68 | # 69 | # You should have received a copy of the GNU General Public License along 70 | # with this program. If not, see . 71 | # 72 | # As a special exception, the respective Autoconf Macro's copyright owner 73 | # gives unlimited permission to copy, distribute and modify the configure 74 | # scripts that are the output of Autoconf when processing the Macro. You 75 | # need not follow the terms of the GNU General Public License when using 76 | # or distributing such scripts, even though portions of the text of the 77 | # Macro appear in them. The GNU General Public License (GPL) does govern 78 | # all other use of the material that constitutes the Autoconf Macro. 79 | # 80 | # This special exception to the GPL applies to versions of the Autoconf 81 | # Macro released by the Autoconf Archive. When you make and distribute a 82 | # modified version of the Autoconf Macro, you may extend this special 83 | # exception to the GPL to apply to your modified version as well. 84 | 85 | #serial 21 86 | 87 | AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) 88 | AC_DEFUN([AX_PTHREAD], [ 89 | AC_REQUIRE([AC_CANONICAL_HOST]) 90 | AC_LANG_PUSH([C]) 91 | ax_pthread_ok=no 92 | 93 | # We used to check for pthread.h first, but this fails if pthread.h 94 | # requires special compiler flags (e.g. on True64 or Sequent). 95 | # It gets checked for in the link test anyway. 96 | 97 | # First of all, check if the user has set any of the PTHREAD_LIBS, 98 | # etcetera environment variables, and if threads linking works using 99 | # them: 100 | if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then 101 | save_CFLAGS="$CFLAGS" 102 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 103 | save_LIBS="$LIBS" 104 | LIBS="$PTHREAD_LIBS $LIBS" 105 | AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) 106 | AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) 107 | AC_MSG_RESULT([$ax_pthread_ok]) 108 | if test x"$ax_pthread_ok" = xno; then 109 | PTHREAD_LIBS="" 110 | PTHREAD_CFLAGS="" 111 | fi 112 | LIBS="$save_LIBS" 113 | CFLAGS="$save_CFLAGS" 114 | fi 115 | 116 | # We must check for the threads library under a number of different 117 | # names; the ordering is very important because some systems 118 | # (e.g. DEC) have both -lpthread and -lpthreads, where one of the 119 | # libraries is broken (non-POSIX). 120 | 121 | # Create a list of thread flags to try. Items starting with a "-" are 122 | # C compiler flags, and other items are library names, except for "none" 123 | # which indicates that we try without any flags at all, and "pthread-config" 124 | # which is a program returning the flags for the Pth emulation library. 125 | 126 | ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" 127 | 128 | # The ordering *is* (sometimes) important. Some notes on the 129 | # individual items follow: 130 | 131 | # pthreads: AIX (must check this before -lpthread) 132 | # none: in case threads are in libc; should be tried before -Kthread and 133 | # other compiler flags to prevent continual compiler warnings 134 | # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) 135 | # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) 136 | # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) 137 | # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) 138 | # -pthreads: Solaris/gcc 139 | # -mthreads: Mingw32/gcc, Lynx/gcc 140 | # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it 141 | # doesn't hurt to check since this sometimes defines pthreads too; 142 | # also defines -D_REENTRANT) 143 | # ... -mt is also the pthreads flag for HP/aCC 144 | # pthread: Linux, etcetera 145 | # --thread-safe: KAI C++ 146 | # pthread-config: use pthread-config program (for GNU Pth library) 147 | 148 | case ${host_os} in 149 | solaris*) 150 | 151 | # On Solaris (at least, for some versions), libc contains stubbed 152 | # (non-functional) versions of the pthreads routines, so link-based 153 | # tests will erroneously succeed. (We need to link with -pthreads/-mt/ 154 | # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather 155 | # a function called by this macro, so we could check for that, but 156 | # who knows whether they'll stub that too in a future libc.) So, 157 | # we'll just look for -pthreads and -lpthread first: 158 | 159 | ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" 160 | ;; 161 | 162 | darwin*) 163 | ax_pthread_flags="-pthread $ax_pthread_flags" 164 | ;; 165 | esac 166 | 167 | # Clang doesn't consider unrecognized options an error unless we specify 168 | # -Werror. We throw in some extra Clang-specific options to ensure that 169 | # this doesn't happen for GCC, which also accepts -Werror. 170 | 171 | AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) 172 | save_CFLAGS="$CFLAGS" 173 | ax_pthread_extra_flags="-Werror" 174 | CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" 175 | AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], 176 | [AC_MSG_RESULT([yes])], 177 | [ax_pthread_extra_flags= 178 | AC_MSG_RESULT([no])]) 179 | CFLAGS="$save_CFLAGS" 180 | 181 | if test x"$ax_pthread_ok" = xno; then 182 | for flag in $ax_pthread_flags; do 183 | 184 | case $flag in 185 | none) 186 | AC_MSG_CHECKING([whether pthreads work without any flags]) 187 | ;; 188 | 189 | -*) 190 | AC_MSG_CHECKING([whether pthreads work with $flag]) 191 | PTHREAD_CFLAGS="$flag" 192 | ;; 193 | 194 | pthread-config) 195 | AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) 196 | if test x"$ax_pthread_config" = xno; then continue; fi 197 | PTHREAD_CFLAGS="`pthread-config --cflags`" 198 | PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" 199 | ;; 200 | 201 | *) 202 | AC_MSG_CHECKING([for the pthreads library -l$flag]) 203 | PTHREAD_LIBS="-l$flag" 204 | ;; 205 | esac 206 | 207 | save_LIBS="$LIBS" 208 | save_CFLAGS="$CFLAGS" 209 | LIBS="$PTHREAD_LIBS $LIBS" 210 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" 211 | 212 | # Check for various functions. We must include pthread.h, 213 | # since some functions may be macros. (On the Sequent, we 214 | # need a special flag -Kthread to make this header compile.) 215 | # We check for pthread_join because it is in -lpthread on IRIX 216 | # while pthread_create is in libc. We check for pthread_attr_init 217 | # due to DEC craziness with -lpthreads. We check for 218 | # pthread_cleanup_push because it is one of the few pthread 219 | # functions on Solaris that doesn't have a non-functional libc stub. 220 | # We try pthread_create on general principles. 221 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include 222 | static void routine(void *a) { a = 0; } 223 | static void *start_routine(void *a) { return a; }], 224 | [pthread_t th; pthread_attr_t attr; 225 | pthread_create(&th, 0, start_routine, 0); 226 | pthread_join(th, 0); 227 | pthread_attr_init(&attr); 228 | pthread_cleanup_push(routine, 0); 229 | pthread_cleanup_pop(0) /* ; */])], 230 | [ax_pthread_ok=yes], 231 | []) 232 | 233 | LIBS="$save_LIBS" 234 | CFLAGS="$save_CFLAGS" 235 | 236 | AC_MSG_RESULT([$ax_pthread_ok]) 237 | if test "x$ax_pthread_ok" = xyes; then 238 | break; 239 | fi 240 | 241 | PTHREAD_LIBS="" 242 | PTHREAD_CFLAGS="" 243 | done 244 | fi 245 | 246 | # Various other checks: 247 | if test "x$ax_pthread_ok" = xyes; then 248 | save_LIBS="$LIBS" 249 | LIBS="$PTHREAD_LIBS $LIBS" 250 | save_CFLAGS="$CFLAGS" 251 | CFLAGS="$CFLAGS $PTHREAD_CFLAGS" 252 | 253 | # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. 254 | AC_MSG_CHECKING([for joinable pthread attribute]) 255 | attr_name=unknown 256 | for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do 257 | AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], 258 | [int attr = $attr; return attr /* ; */])], 259 | [attr_name=$attr; break], 260 | []) 261 | done 262 | AC_MSG_RESULT([$attr_name]) 263 | if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then 264 | AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], 265 | [Define to necessary symbol if this constant 266 | uses a non-standard name on your system.]) 267 | fi 268 | 269 | AC_MSG_CHECKING([if more special flags are required for pthreads]) 270 | flag=no 271 | case ${host_os} in 272 | aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; 273 | osf* | hpux*) flag="-D_REENTRANT";; 274 | solaris*) 275 | if test "$GCC" = "yes"; then 276 | flag="-D_REENTRANT" 277 | else 278 | # TODO: What about Clang on Solaris? 279 | flag="-mt -D_REENTRANT" 280 | fi 281 | ;; 282 | esac 283 | AC_MSG_RESULT([$flag]) 284 | if test "x$flag" != xno; then 285 | PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" 286 | fi 287 | 288 | AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], 289 | [ax_cv_PTHREAD_PRIO_INHERIT], [ 290 | AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], 291 | [[int i = PTHREAD_PRIO_INHERIT;]])], 292 | [ax_cv_PTHREAD_PRIO_INHERIT=yes], 293 | [ax_cv_PTHREAD_PRIO_INHERIT=no]) 294 | ]) 295 | AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], 296 | [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) 297 | 298 | LIBS="$save_LIBS" 299 | CFLAGS="$save_CFLAGS" 300 | 301 | # More AIX lossage: compile with *_r variant 302 | if test "x$GCC" != xyes; then 303 | case $host_os in 304 | aix*) 305 | AS_CASE(["x/$CC"], 306 | [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], 307 | [#handle absolute path differently from PATH based program lookup 308 | AS_CASE(["x$CC"], 309 | [x/*], 310 | [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], 311 | [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) 312 | ;; 313 | esac 314 | fi 315 | fi 316 | 317 | test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" 318 | 319 | AC_SUBST([PTHREAD_LIBS]) 320 | AC_SUBST([PTHREAD_CFLAGS]) 321 | AC_SUBST([PTHREAD_CC]) 322 | 323 | # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: 324 | if test x"$ax_pthread_ok" = xyes; then 325 | ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) 326 | : 327 | else 328 | ax_pthread_ok=no 329 | $2 330 | fi 331 | AC_LANG_POP 332 | ])dnl AX_PTHREAD 333 | -------------------------------------------------------------------------------- /openarc/.gitignore: -------------------------------------------------------------------------------- 1 | .deps/* 2 | openarc.8 3 | openarc.conf.5 4 | openarc 5 | openarc.conf.simple 6 | -------------------------------------------------------------------------------- /openarc/Makefile.am: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2010-2014, 2016, 2017, The Trusted Domain Project. 2 | # All rights reserved. 3 | 4 | if DEBUG 5 | AM_CFLAGS = -g 6 | endif 7 | 8 | if BUILD_FILTER 9 | dist_doc_DATA = openarc.conf.sample openarc.conf.simple 10 | 11 | man_MANS = openarc.conf.5 openarc.8 12 | 13 | sbin_PROGRAMS = openarc 14 | openarc_SOURCES = config.c config.h openarc.c openarc.h openarc-ar.c openarc-ar.h openarc-config.h openarc-crypto.c openarc-crypto.h openarc-test.c openarc-test.h util.c util.h 15 | openarc_CC = $(PTHREAD_CC) 16 | openarc_CFLAGS = $(PTHREAD_CFLAGS) $(LIBCRYPTO_CFLAGS) 17 | openarc_CPPFLAGS = -I$(srcdir)/../libopenarc $(LIBCRYPTO_CPPFLAGS) $(LIBMILTER_INCDIRS) 18 | openarc_LDFLAGS = $(LIBCRYPTO_LIBDIRS) $(LIBMILTER_LIBDIRS) $(PTHREAD_CFLAGS) 19 | openarc_LDADD = ../libopenarc/libopenarc.la $(LIBMILTER_LIBS) $(LIBCRYPTO_LIBS) $(PTHREAD_LIBS) $(LIBRESOLV) 20 | endif 21 | -------------------------------------------------------------------------------- /openarc/config.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2006-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2015, 2017, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #include "build-config.h" 10 | 11 | /* for Solaris */ 12 | #ifndef _REENTRANT 13 | # define _REENTRANT 14 | #endif /* _REENTRANT */ 15 | 16 | /* system includes */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* libopenarc includes */ 24 | #include 25 | 26 | /* libbsd if found */ 27 | #ifdef USE_BSD_H 28 | # include 29 | #endif /* USE_BSD_H */ 30 | 31 | /* libstrl if needed */ 32 | #ifdef USE_STRL_H 33 | # include 34 | #endif /* USE_STRL_H */ 35 | 36 | /* opendkim includes */ 37 | #include "config.h" 38 | 39 | /* limits */ 40 | #define BUFRSZ 1024 /* generic buffer size */ 41 | #define MAXLEVEL 5 /* max. include recursion */ 42 | 43 | #ifndef FALSE 44 | # define FALSE 0 45 | #endif /* ! FALSE */ 46 | #ifndef TRUE 47 | # define TRUE 1 48 | #endif /* ! TRUE */ 49 | 50 | /* prototypes */ 51 | static void config_attach __P((struct config *, struct config **)); 52 | 53 | /* errors */ 54 | #define CONF_UNKNOWN (-1) /* unknown status */ 55 | #define CONF_SUCCESS 0 /* no error */ 56 | #define CONF_MISSING 1 /* required value missing */ 57 | #define CONF_UNRECOG 2 /* unrecognized parameter */ 58 | #define CONF_ILLEGAL 3 /* illegal value */ 59 | #define CONF_NESTING 4 /* "include" nesting too deep */ 60 | #define CONF_READING 5 /* error reading (see errno) */ 61 | #define CONF_NMEMORY 6 /* malloc() failure */ 62 | 63 | /* statics */ 64 | static int conf_error; /* configuration error number */ 65 | 66 | /* 67 | ** CONFIG_GETLINE -- read a line of arbitrary length from a stream 68 | ** 69 | ** Parameters: 70 | ** in -- input stream 71 | ** 72 | ** Return value: 73 | ** NULL on EOF, otherwise a newly-allocated string containing the next 74 | ** line from "in". 75 | */ 76 | 77 | static char * 78 | config_getline(FILE *in) 79 | { 80 | int c; 81 | size_t asize = BUFRSZ; 82 | size_t len = 0; 83 | char *new = NULL; 84 | 85 | assert(in != NULL); 86 | 87 | new = malloc(asize); 88 | if (new == NULL) 89 | return NULL; 90 | new[0] = '\0'; 91 | 92 | for (;;) 93 | { 94 | c = fgetc(in); 95 | if (c == '\n') 96 | { 97 | break; 98 | } 99 | else if (c == EOF) 100 | { 101 | if (len == 0) 102 | { 103 | free(new); 104 | new = NULL; 105 | } 106 | break; 107 | } 108 | 109 | if (len == asize - 1) 110 | { 111 | char *newnew; 112 | 113 | asize += BUFRSZ; 114 | 115 | newnew = realloc(new, asize); 116 | if (newnew == NULL) 117 | { 118 | free(new); 119 | return NULL; 120 | } 121 | 122 | new = newnew; 123 | } 124 | 125 | new[len++] = c; 126 | new[len] = '\0'; 127 | } 128 | 129 | return new; 130 | } 131 | 132 | /* 133 | ** CONFIG_ATTACH -- attach one config to another 134 | ** 135 | ** Parameters: 136 | ** c1 -- configuration to attach 137 | ** c2 -- configuration to which to attach 138 | ** 139 | ** Return value: 140 | ** None. 141 | */ 142 | 143 | static void 144 | config_attach(struct config *c1, struct config **c2) 145 | { 146 | struct config *prev; 147 | struct config *cur; 148 | 149 | assert(c1 != NULL); 150 | 151 | if (*c2 == NULL) 152 | { 153 | *c2 = c1; 154 | } 155 | else 156 | { 157 | prev = NULL; 158 | 159 | for (cur = c1; cur != NULL; cur = cur->cfg_next) 160 | prev = cur; 161 | 162 | prev->cfg_next = *c2; 163 | } 164 | } 165 | 166 | /* 167 | ** CONFIG_LOAD_LEVEL -- load configuration from a file (internal version) 168 | ** 169 | ** Parameters: 170 | ** file -- path from which to load; NULL or "-" implies stdin 171 | ** cd -- array of (struct configdef) elements containing the 172 | ** configuration syntax to assert 173 | ** line -- line number where an error occurred (updated) 174 | ** outpath -- configuration file in which error occurred (updated) 175 | ** outpathlen -- bytes available at "outpath" 176 | ** level -- nesting level 177 | ** deprecated -- string containing list of deprecated items (updated) 178 | ** 179 | ** Return value: 180 | ** Pointer to a (struct config) which is the head of a list of 181 | ** loaded configuration items, or NULL on error; if NULL, "line" is 182 | ** updated to indicate which line number contained the error and, 183 | ** if the configuration file being parsed was not the one referenced 184 | ** by "in", then "path" will be updated to point to the filename 185 | ** that was being processed. 186 | */ 187 | 188 | static struct config * 189 | config_load_level(char *file, struct configdef *def, 190 | unsigned int *line, char *outpath, size_t outpathlen, 191 | int level, char **deprecated) 192 | { 193 | int n = -1; 194 | int err = 0; 195 | unsigned int myline = 0; 196 | int value = -1; 197 | FILE *in; 198 | char *p; 199 | char *s; 200 | char *str = NULL; 201 | char *buf; 202 | struct config *new = NULL; 203 | struct config *cur = NULL; 204 | 205 | assert(def != NULL); 206 | 207 | if (level > MAXLEVEL) 208 | { 209 | conf_error = CONF_NESTING; 210 | return NULL; 211 | } 212 | 213 | if (file == NULL || (file[0] == '-' && file[1] == '\0')) 214 | { 215 | in = stdin; 216 | file = "(stdin)"; 217 | } 218 | else 219 | { 220 | in = fopen(file, "r"); 221 | if (in == NULL) 222 | { 223 | conf_error = CONF_READING; 224 | if (line != NULL) 225 | *line = myline; 226 | if (outpath != NULL) 227 | strlcpy(outpath, file, outpathlen); 228 | return NULL; 229 | } 230 | } 231 | 232 | while ((buf = config_getline(in)) != NULL) 233 | { 234 | myline++; 235 | str = NULL; 236 | 237 | /* read a line; truncate at carriage return, newline, or "#" */ 238 | for (p = buf; *p != '\0'; p++) 239 | { 240 | if (*p == '#' || *p == 0x0D) 241 | { 242 | *p = '\0'; 243 | break; 244 | } 245 | } 246 | 247 | /* break down the line */ 248 | p = strtok_r(buf, " \t", &s); 249 | if (p != NULL) 250 | { 251 | /* recognize the directive? */ 252 | for (n = 0; ; n++) 253 | { 254 | /* nope */ 255 | if (def[n].cd_name == NULL) 256 | { 257 | conf_error = CONF_UNRECOG; 258 | err = 1; 259 | break; 260 | } 261 | 262 | if (strcasecmp(def[n].cd_name, p) == 0) 263 | break; 264 | } 265 | 266 | if (!err) 267 | { 268 | char *q; 269 | 270 | /* skip leading whitespace on value */ 271 | for (p = s; *p == ' ' || *p == '\t'; p++) 272 | continue; 273 | 274 | /* ...and trim trailing whitespace */ 275 | q = p + strlen(p) - 1; 276 | while (p <= q && (*q == '\t' || *q == ' ')) 277 | *q-- = '\0'; 278 | } 279 | 280 | if (*p == '\0' && !err) 281 | { 282 | conf_error = CONF_MISSING; 283 | err = 1; 284 | } 285 | 286 | if (!err) 287 | { 288 | char *q; 289 | 290 | switch (def[n].cd_type) 291 | { 292 | case CONFIG_TYPE_DEPRECATED: 293 | if (deprecated == NULL) 294 | { 295 | break; 296 | } 297 | else if (*deprecated == NULL) 298 | { 299 | *deprecated = strdup(def[n].cd_name); 300 | } 301 | else 302 | { 303 | char *new; 304 | size_t oldlen; 305 | size_t newlen; 306 | 307 | oldlen = strlen(*deprecated); 308 | newlen = oldlen + 2 + 309 | strlen(def[n].cd_name); 310 | new = realloc(*deprecated, 311 | newlen); 312 | if (new != NULL) 313 | { 314 | new[oldlen] = ','; 315 | new[oldlen + 1] = '\0'; 316 | strlcat(*deprecated, 317 | def[n].cd_name, 318 | newlen); 319 | *deprecated = new; 320 | } 321 | } 322 | break; 323 | 324 | case CONFIG_TYPE_STRING: 325 | case CONFIG_TYPE_INCLUDE: 326 | str = p; 327 | break; 328 | 329 | case CONFIG_TYPE_BOOLEAN: 330 | if (p[0] == 't' || 331 | p[0] == 'T' || 332 | p[0] == 'y' || 333 | p[0] == 'Y' || 334 | p[0] == '1') 335 | { 336 | value = 1; 337 | } 338 | else if (p[0] == 'f' || 339 | p[0] == 'F' || 340 | p[0] == 'n' || 341 | p[0] == 'N' || 342 | p[0] == '0') 343 | { 344 | value = 0; 345 | } 346 | else 347 | { 348 | conf_error = CONF_ILLEGAL; 349 | err = 1; 350 | } 351 | 352 | break; 353 | 354 | case CONFIG_TYPE_INTEGER: 355 | value = (int) strtol(p, &q, 0); 356 | if (*q != '\0') 357 | { 358 | conf_error = CONF_ILLEGAL; 359 | err = 1; 360 | } 361 | 362 | str = p; 363 | 364 | break; 365 | 366 | default: 367 | assert(0); 368 | /* NOTREACHED */ 369 | return NULL; 370 | } 371 | } 372 | } 373 | else 374 | { 375 | free(buf); 376 | continue; /* blank line */ 377 | } 378 | 379 | /* a parse error, or only one argument, is no good */ 380 | if (err) 381 | { 382 | config_free(cur); 383 | 384 | if (line != NULL) 385 | *line = myline; 386 | if (outpath != NULL) 387 | strlcpy(outpath, file, outpathlen); 388 | 389 | if (in != stdin) 390 | fclose(in); 391 | 392 | free(buf); 393 | return NULL; 394 | } 395 | 396 | if (def[n].cd_type != CONFIG_TYPE_INCLUDE && 397 | def[n].cd_type != CONFIG_TYPE_DEPRECATED) 398 | { 399 | new = (struct config *) malloc(sizeof(struct config)); 400 | if (new == NULL) 401 | { 402 | config_free(cur); 403 | 404 | conf_error = CONF_NMEMORY; 405 | 406 | if (line != NULL) 407 | *line = myline; 408 | if (outpath != NULL) 409 | strlcpy(outpath, file, outpathlen); 410 | 411 | if (in != stdin) 412 | fclose(in); 413 | 414 | free(buf); 415 | return NULL; 416 | } 417 | 418 | new->cfg_next = cur; 419 | new->cfg_name = def[n].cd_name; 420 | new->cfg_type = def[n].cd_type; 421 | } 422 | 423 | switch (def[n].cd_type) 424 | { 425 | case CONFIG_TYPE_INCLUDE: 426 | { 427 | struct config *incl; 428 | 429 | incl = config_load_level(str, def, line, outpath, 430 | outpathlen, level + 1, deprecated); 431 | if (incl == NULL) 432 | { 433 | if (in != stdin) 434 | fclose(in); 435 | 436 | free(buf); 437 | return NULL; 438 | } 439 | 440 | config_attach(incl, &cur); 441 | new = incl; 442 | 443 | break; 444 | } 445 | 446 | case CONFIG_TYPE_STRING: 447 | new->cfg_string = strdup(str); 448 | break; 449 | 450 | case CONFIG_TYPE_BOOLEAN: 451 | new->cfg_bool = (_Bool) value; 452 | break; 453 | 454 | case CONFIG_TYPE_INTEGER: 455 | new->cfg_int = value; 456 | break; 457 | 458 | case CONFIG_TYPE_DEPRECATED: 459 | break; 460 | 461 | default: 462 | assert(0); 463 | } 464 | 465 | cur = new; 466 | 467 | free(buf); 468 | } 469 | 470 | conf_error = CONF_SUCCESS; 471 | 472 | if (in != stdin) 473 | fclose(in); 474 | 475 | if (myline == 0 || cur == NULL) 476 | { 477 | cur = (struct config *) malloc(sizeof *cur); 478 | if (cur != NULL) 479 | { 480 | cur->cfg_bool = FALSE; 481 | cur->cfg_type = CONFIG_TYPE_STRING; 482 | cur->cfg_int = 0; 483 | cur->cfg_name = ""; 484 | cur->cfg_string = NULL; 485 | cur->cfg_next = NULL; 486 | 487 | return cur; 488 | } 489 | else 490 | { 491 | conf_error = CONF_NMEMORY; 492 | 493 | if (line != NULL) 494 | *line = myline; 495 | if (outpath != NULL) 496 | strlcpy(outpath, file, outpathlen); 497 | 498 | return NULL; 499 | } 500 | } 501 | else 502 | { 503 | return cur; 504 | } 505 | } 506 | 507 | /* 508 | ** CONFIG_ERROR -- return a string describing a configuration error 509 | ** 510 | ** Parameters: 511 | ** None. 512 | ** 513 | ** Return value: 514 | ** Pointer to a NULL-terminated string explaining the last error. 515 | */ 516 | 517 | char * 518 | config_error(void) 519 | { 520 | switch (conf_error) 521 | { 522 | case CONF_SUCCESS: 523 | return "no error"; 524 | 525 | case CONF_MISSING: 526 | return "required value missing"; 527 | 528 | case CONF_UNRECOG: 529 | return "unrecognized parameter"; 530 | 531 | case CONF_ILLEGAL: 532 | return "illegal value"; 533 | 534 | case CONF_NESTING: 535 | return "nesting too deep"; 536 | 537 | case CONF_READING: 538 | return "error reading configuration file"; 539 | 540 | case CONF_NMEMORY: 541 | return "memory allocation failure"; 542 | 543 | case CONF_UNKNOWN: 544 | default: 545 | return "unknown error"; 546 | } 547 | 548 | /* NOTREACHED */ 549 | } 550 | 551 | /* 552 | ** CONFIG_FREE -- release memory associated with a config list 553 | ** 554 | ** Parameters: 555 | ** head -- head of the config list 556 | ** 557 | ** Return value: 558 | ** None. 559 | */ 560 | 561 | void 562 | config_free(struct config *head) 563 | { 564 | struct config *next; 565 | struct config *cur; 566 | 567 | cur = head; 568 | while (cur != NULL) 569 | { 570 | next = cur->cfg_next; 571 | if (cur->cfg_type == CONFIG_TYPE_STRING && 572 | cur->cfg_string != NULL) 573 | free(cur->cfg_string); 574 | free(cur); 575 | cur = next; 576 | } 577 | } 578 | 579 | /* 580 | ** CONFIG_LOAD -- load configuration from a file 581 | ** 582 | ** Parameters: 583 | ** file -- path from which to load; NULL or "-" implies stdin 584 | ** cd -- array of (struct configdef) elements containing the 585 | ** configuration syntax to assert 586 | ** line -- line number where an error occurred (updated) 587 | ** path -- configuration file in which error occurred (updated) 588 | ** pathlen -- number of bytes available at "path" 589 | ** 590 | ** Return value: 591 | ** Pointer to a (struct config) which is the head of a list of 592 | ** loaded configuration items, or NULL on error; if NULL, "line" is 593 | ** updated to indicate which line number contained the error and, 594 | ** if the configuration file being parsed was not the one referenced 595 | ** by "in", then "path" will be updated to point to the filename 596 | ** that was being processed. 597 | */ 598 | 599 | struct config * 600 | config_load(char *file, struct configdef *def, unsigned int *line, 601 | char *path, size_t pathlen, char **deprecated) 602 | { 603 | conf_error = CONF_UNKNOWN; 604 | 605 | return config_load_level(file, def, line, path, pathlen, 0, deprecated); 606 | } 607 | 608 | /* 609 | ** CONFIG_CHECK -- verify that stuff marked "required" is present 610 | ** 611 | ** Parameters: 612 | ** head -- head of config list 613 | ** def -- definitions 614 | ** 615 | ** Return value: 616 | ** Name of the first parameter in "def" that was marked "required" 617 | ** yet absent from the configuration parsed, or NULL if nothing 618 | ** required was missing. 619 | */ 620 | 621 | char * 622 | config_check(struct config *head, struct configdef *def) 623 | { 624 | int n; 625 | struct config *cur; 626 | 627 | assert(head != NULL); 628 | assert(def != NULL); 629 | 630 | conf_error = CONF_UNKNOWN; 631 | 632 | for (n = 0; ; n++) 633 | { 634 | if (def[n].cd_name == NULL) 635 | { 636 | conf_error = CONF_SUCCESS; 637 | return NULL; 638 | } 639 | if (!def[n].cd_req) 640 | continue; 641 | 642 | for (cur = head; cur != NULL; cur = cur->cfg_next) 643 | { 644 | if (cur->cfg_name == def[n].cd_name) 645 | break; 646 | } 647 | 648 | if (cur == NULL) 649 | { 650 | conf_error = CONF_MISSING; 651 | 652 | return def[n].cd_name; 653 | } 654 | } 655 | 656 | /* NOTREACHED */ 657 | } 658 | 659 | /* 660 | ** CONFIG_GET -- retrieve a parameter's value 661 | ** 662 | ** Parameter: 663 | ** head -- head of config list 664 | ** name -- name of the parameter of interest 665 | ** value -- where to write the result (returned) 666 | ** size -- bytes available at "value" 667 | ** 668 | ** Return value: 669 | ** 1 if the data was found, 0 otherwise, -1 if the request was illegal 670 | ** 671 | ** Notes: 672 | ** "value" is a (void *). It can be used directly, such as: 673 | ** 674 | ** int x; 675 | ** 676 | ** (void) config_get(conflist, "MyInteger", (void *) &x); 677 | */ 678 | 679 | int 680 | config_get(struct config *head, const char *name, void *value, size_t size) 681 | { 682 | struct config *cur; 683 | 684 | assert(head != NULL); 685 | assert(name != NULL); 686 | assert(value != NULL); 687 | assert(size > 0); 688 | 689 | conf_error = CONF_UNKNOWN; 690 | 691 | for (cur = head; cur != NULL; cur = cur->cfg_next) 692 | { 693 | if (strcasecmp(cur->cfg_name, name) == 0) 694 | { 695 | switch (cur->cfg_type) 696 | { 697 | case CONFIG_TYPE_BOOLEAN: 698 | if (size != sizeof(_Bool)) 699 | { 700 | conf_error = CONF_ILLEGAL; 701 | return -1; 702 | } 703 | memcpy(value, &cur->cfg_bool, size); 704 | break; 705 | 706 | case CONFIG_TYPE_INTEGER: 707 | if (size != sizeof(int)) 708 | { 709 | conf_error = CONF_ILLEGAL; 710 | return -1; 711 | } 712 | memcpy(value, &cur->cfg_int, size); 713 | break; 714 | 715 | case CONFIG_TYPE_INCLUDE: 716 | conf_error = CONF_ILLEGAL; 717 | return -1; 718 | 719 | default: 720 | if (size != sizeof(char *)) 721 | { 722 | conf_error = CONF_ILLEGAL; 723 | return -1; 724 | } 725 | memcpy(value, &cur->cfg_string, size); 726 | break; 727 | } 728 | 729 | return 1; 730 | } 731 | } 732 | 733 | conf_error = CONF_SUCCESS; 734 | 735 | return 0; 736 | } 737 | 738 | /* 739 | ** CONFIG_VALIDNAME -- return True IFF the name provided was valid 740 | ** 741 | ** Parameters: 742 | ** def -- configuration definition 743 | ** name -- name of value of interest 744 | ** 745 | ** Return value: 746 | ** True IFF "name" was defined inside "cd" 747 | */ 748 | 749 | _Bool 750 | config_validname(struct configdef *def, const char *name) 751 | { 752 | unsigned int n; 753 | 754 | assert(def != NULL); 755 | assert(name != NULL); 756 | 757 | for (n = 0; ; n++) 758 | { 759 | if (def[n].cd_name == NULL) 760 | return FALSE; 761 | 762 | if (strcasecmp(name, def[n].cd_name) == 0 && 763 | def[n].cd_type != CONFIG_TYPE_DEPRECATED) 764 | return TRUE; 765 | } 766 | 767 | assert(0); 768 | /* NOTREACHED */ 769 | } 770 | 771 | /* 772 | ** CONFIG_DUMP -- dump configuration contents 773 | ** 774 | ** Parameters: 775 | ** cfg -- head of assembled configuration values 776 | ** out -- stream to which to write 777 | ** name -- name of value of interest 778 | ** 779 | ** Return value: 780 | ** Number of items that matched. 781 | */ 782 | 783 | unsigned int 784 | config_dump(struct config *cfg, FILE *out, const char *name) 785 | { 786 | unsigned int nprinted = 0; 787 | struct config *cur; 788 | 789 | assert(cfg != NULL); 790 | assert(out != NULL); 791 | 792 | for (cur = cfg; cur != NULL; cur = cur->cfg_next) 793 | { 794 | if (name != NULL) 795 | { 796 | if (strcasecmp(name, cur->cfg_name) != 0) 797 | continue; 798 | } 799 | else 800 | { 801 | fprintf(out, "%p: \"%s\" ", cur, cur->cfg_name); 802 | } 803 | 804 | switch (cur->cfg_type) 805 | { 806 | case CONFIG_TYPE_STRING: 807 | fprintf(out, "%s\n", cur->cfg_string); 808 | break; 809 | 810 | case CONFIG_TYPE_INTEGER: 811 | fprintf(out, "%d\n", cur->cfg_int); 812 | break; 813 | 814 | case CONFIG_TYPE_BOOLEAN: 815 | fprintf(out, "%s\n", cur->cfg_bool ? "True" : "False"); 816 | break; 817 | 818 | default: 819 | assert(0); 820 | } 821 | 822 | nprinted++; 823 | } 824 | 825 | return nprinted; 826 | } 827 | -------------------------------------------------------------------------------- /openarc/config.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2006-2008 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2012, 2015, The Trusted Domain Project. All rights reserved. 6 | ** 7 | */ 8 | 9 | #ifndef _CONFIG_H_ 10 | #define _CONFIG_H_ 11 | 12 | #include "build-config.h" 13 | 14 | /* system includes */ 15 | #include 16 | #ifdef HAVE_STDBOOL_H 17 | # include 18 | #endif /* HAVE_STDBOOL_H */ 19 | #include 20 | 21 | /* types and things */ 22 | #define CONFIG_TYPE_STRING 0 23 | #define CONFIG_TYPE_INTEGER 1 24 | #define CONFIG_TYPE_BOOLEAN 2 25 | #define CONFIG_TYPE_INCLUDE 3 26 | #define CONFIG_TYPE_DEPRECATED 4 27 | 28 | struct config 29 | { 30 | _Bool cfg_bool; 31 | u_int cfg_type; 32 | int cfg_int; 33 | char * cfg_name; 34 | char * cfg_string; 35 | struct config * cfg_next; 36 | }; 37 | 38 | struct configdef 39 | { 40 | char * cd_name; 41 | u_int cd_type; 42 | _Bool cd_req; 43 | }; 44 | 45 | /* prototypes */ 46 | extern char *config_check __P((struct config *, struct configdef *)); 47 | extern unsigned int config_dump __P((struct config *, FILE *, const char *)); 48 | extern char *config_error __P((void)); 49 | extern void config_free __P((struct config *)); 50 | extern int config_get __P((struct config *, const char *, void *, size_t)); 51 | extern struct config *config_load __P((char *, struct configdef *, 52 | unsigned int *, char *, size_t, char **)); 53 | extern _Bool config_validname __P((struct configdef *, const char *)); 54 | 55 | #endif /* _CONFIG_H_ */ 56 | -------------------------------------------------------------------------------- /openarc/openarc-ar.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009, 2011-2014, 2016, 2017, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #include "build-config.h" 10 | 11 | /* system includes */ 12 | #include 13 | #include 14 | #ifdef HAVE_STDBOOL_H 15 | # include 16 | #endif /* HAVE_STDBOOL_H */ 17 | #include 18 | #include 19 | #include 20 | #ifdef ARTEST 21 | # include 22 | #endif /* ARTEST */ 23 | 24 | /* libbsd if found */ 25 | #ifdef USE_BSD_H 26 | # include 27 | #endif /* USE_BSD_H */ 28 | 29 | /* libstrl if needed */ 30 | #ifdef USE_STRL_H 31 | # include 32 | #endif /* USE_STRL_H */ 33 | 34 | /* openarc includes */ 35 | #include "openarc-ar.h" 36 | 37 | /* macros */ 38 | #define ARES_ENDOF(x) ((x) + sizeof(x) - 1) 39 | #define ARES_STRORNULL(x) ((x) == NULL ? "(null)" : (x)) 40 | #define ARES_TOKENS ";=." 41 | #define ARES_TOKENS2 "=." 42 | 43 | #define ARES_MAXTOKENS 512 44 | 45 | /* tables */ 46 | struct lookup 47 | { 48 | char * str; 49 | int code; 50 | }; 51 | 52 | struct lookup methods[] = 53 | { 54 | { "arc", ARES_METHOD_ARC }, 55 | { "auth", ARES_METHOD_AUTH }, 56 | { "dkim", ARES_METHOD_DKIM }, 57 | { "dkim-adsp", ARES_METHOD_DKIMADSP }, 58 | { "dkim-atps", ARES_METHOD_DKIMATPS }, 59 | { "dmarc", ARES_METHOD_DMARC }, 60 | { "domainkeys", ARES_METHOD_DOMAINKEYS }, 61 | { "iprev", ARES_METHOD_IPREV }, 62 | { "rrvs", ARES_METHOD_RRVS }, 63 | { "sender-id", ARES_METHOD_SENDERID }, 64 | { "smime", ARES_METHOD_SMIME }, 65 | { "spf", ARES_METHOD_SPF }, 66 | { NULL, ARES_METHOD_UNKNOWN } 67 | }; 68 | 69 | struct lookup aresults[] = 70 | { 71 | { "none", ARES_RESULT_NONE }, 72 | { "pass", ARES_RESULT_PASS }, 73 | { "fail", ARES_RESULT_FAIL }, 74 | { "policy", ARES_RESULT_POLICY }, 75 | { "neutral", ARES_RESULT_NEUTRAL }, 76 | { "temperror", ARES_RESULT_TEMPERROR }, 77 | { "permerror", ARES_RESULT_PERMERROR }, 78 | { "nxdomain", ARES_RESULT_NXDOMAIN }, 79 | { "signed", ARES_RESULT_SIGNED }, 80 | { "unknown", ARES_RESULT_UNKNOWN }, 81 | { "discard", ARES_RESULT_DISCARD }, 82 | { "softfail", ARES_RESULT_SOFTFAIL }, 83 | { NULL, ARES_RESULT_UNKNOWN } 84 | }; 85 | 86 | struct lookup ptypes[] = 87 | { 88 | { "smtp", ARES_PTYPE_SMTP }, 89 | { "header", ARES_PTYPE_HEADER }, 90 | { "body", ARES_PTYPE_BODY }, 91 | { "policy", ARES_PTYPE_POLICY }, 92 | { NULL, ARES_PTYPE_UNKNOWN } 93 | }; 94 | 95 | /* 96 | ** ARES_TOKENIZE -- tokenize a string 97 | ** 98 | ** Parameters: 99 | ** input -- input string 100 | ** outbuf -- output buffer 101 | ** outbuflen -- number of bytes available at "outbuf" 102 | ** tokens -- array of token pointers 103 | ** ntokens -- number of token pointers available at "tokens" 104 | ** 105 | ** Return value: 106 | ** -1 -- not enough space at "outbuf" for tokenizing 107 | ** other -- number of tokens identified; may be greater than 108 | ** "ntokens" if there were more tokens found than there were 109 | ** pointers available. 110 | */ 111 | 112 | static int 113 | ares_tokenize(u_char *input, u_char *outbuf, size_t outbuflen, 114 | u_char **tokens, int ntokens) 115 | { 116 | _Bool quoted = FALSE; 117 | _Bool escaped = FALSE; 118 | _Bool intok = FALSE; 119 | int n = 0; 120 | int parens = 0; 121 | u_char *p; 122 | u_char *q; 123 | u_char *end; 124 | 125 | assert(input != NULL); 126 | assert(outbuf != NULL); 127 | assert(outbuflen > 0); 128 | assert(tokens != NULL); 129 | assert(ntokens > 0); 130 | 131 | q = outbuf; 132 | end = outbuf + outbuflen - 1; 133 | 134 | for (p = input; *p != '\0' && q <= end; p++) 135 | { 136 | if (escaped) /* escape */ 137 | { 138 | if (!intok) 139 | { 140 | if (n < ntokens) 141 | tokens[n] = q; 142 | intok = TRUE; 143 | } 144 | 145 | *q = *p; 146 | q++; 147 | escaped = FALSE; 148 | } 149 | else if (*p == '\\') /* escape */ 150 | { 151 | escaped = TRUE; 152 | } 153 | else if (*p == '"' && parens == 0) /* quoting */ 154 | { 155 | quoted = !quoted; 156 | 157 | if (!intok) 158 | { 159 | if (n < ntokens) 160 | tokens[n] = q; 161 | intok = TRUE; 162 | } 163 | } 164 | else if (*p == '(' && !quoted) /* "(" (comment) */ 165 | { 166 | parens++; 167 | 168 | if (!intok) 169 | { 170 | if (n < ntokens) 171 | tokens[n] = q; 172 | intok = TRUE; 173 | } 174 | 175 | *q = *p; 176 | q++; 177 | 178 | } 179 | else if (*p == ')' && !quoted) /* ")" (comment) */ 180 | { 181 | if (parens > 0) 182 | { 183 | parens--; 184 | 185 | if (parens == 0) 186 | { 187 | intok = FALSE; 188 | n++; 189 | 190 | *q = ')'; 191 | q++; 192 | if (q <= end) 193 | { 194 | *q = '\0'; 195 | q++; 196 | } 197 | } 198 | } 199 | } 200 | else if (quoted) /* quoted character */ 201 | { 202 | *q = *p; 203 | q++; 204 | } 205 | else if (isascii(*p) && isspace(*p)) /* whitespace */ 206 | { 207 | if (quoted || parens > 0) 208 | { 209 | if (intok) 210 | { 211 | *q = *p; 212 | q++; 213 | } 214 | } 215 | else if (intok) 216 | { 217 | intok = FALSE; 218 | *q = '\0'; 219 | q++; 220 | n++; 221 | } 222 | } 223 | else if (strchr(ARES_TOKENS, *p) != NULL) /* delimiter */ 224 | { 225 | if (parens > 0) 226 | { 227 | *q = *p; 228 | q++; 229 | continue; 230 | } 231 | 232 | if (intok) 233 | { 234 | intok = FALSE; 235 | *q = '\0'; 236 | q++; 237 | n++; 238 | } 239 | 240 | if (q <= end) 241 | { 242 | *q = *p; 243 | if (n < ntokens) 244 | { 245 | tokens[n] = q; 246 | n++; 247 | } 248 | q++; 249 | } 250 | 251 | if (q <= end) 252 | { 253 | *q = '\0'; 254 | q++; 255 | } 256 | } 257 | else /* other */ 258 | { 259 | if (!intok) 260 | { 261 | if (n < ntokens) 262 | tokens[n] = q; 263 | intok = TRUE; 264 | } 265 | 266 | *q = *p; 267 | q++; 268 | } 269 | } 270 | 271 | if (q >= end) 272 | return -1; 273 | 274 | if (intok) 275 | { 276 | *q = '\0'; 277 | n++; 278 | } 279 | 280 | return n; 281 | } 282 | 283 | /* 284 | ** ARES_CONVERT -- convert a string to its code 285 | ** 286 | ** Parameters: 287 | ** table -- in which table to look up 288 | ** str -- string to find 289 | ** 290 | ** Return value: 291 | ** A code translation of "str". 292 | */ 293 | 294 | static int 295 | ares_convert(struct lookup *table, char *str) 296 | { 297 | int c; 298 | 299 | assert(table != NULL); 300 | assert(str != NULL); 301 | 302 | for (c = 0; ; c++) 303 | { 304 | if (table[c].str == NULL || 305 | strcasecmp(table[c].str, str) == 0) 306 | return table[c].code; 307 | } 308 | 309 | /* NOTREACHED */ 310 | } 311 | 312 | /* 313 | ** ARES_XCONVERT -- convert a code to its string 314 | ** 315 | ** Parameters: 316 | ** table -- in which table to look up 317 | ** code -- code to find 318 | ** 319 | ** Return value: 320 | ** A string translation of "code". 321 | */ 322 | 323 | static char * 324 | ares_xconvert(struct lookup *table, int code) 325 | { 326 | int c; 327 | 328 | assert(table != NULL); 329 | 330 | for (c = 0; ; c++) 331 | { 332 | if (table[c].str == NULL || table[c].code == code) 333 | return table[c].str; 334 | } 335 | 336 | /* NOTREACHED */ 337 | } 338 | 339 | /* 340 | ** ARES_DEDUP -- if we've gotten multiple results of the same method, 341 | ** discard the older one 342 | ** 343 | ** Parameters: 344 | ** ar -- pointer to a (struct authres) 345 | ** n -- the last one that was loaded 346 | ** 347 | ** Return value: 348 | ** TRUE iff a de-duplication happened, leaving the result referenced by 349 | ** "n" open. 350 | */ 351 | 352 | static _Bool 353 | ares_dedup(struct authres *ar, int n) 354 | { 355 | int c; 356 | 357 | for (c = 0; c < n; c++) 358 | { 359 | if (ar->ares_result[c].result_method == ar->ares_result[n].result_method && 360 | ar->ares_result[c].result_method != ARES_METHOD_DKIM) 361 | { 362 | memcpy(&ar->ares_result[c], &ar->ares_result[n], 363 | sizeof(ar->ares_result[c])); 364 | return TRUE; 365 | } 366 | } 367 | 368 | return FALSE; 369 | } 370 | 371 | /* 372 | ** ARES_PARSE -- parse an Authentication-Results: header, return a 373 | ** structure containing a parsed result 374 | ** 375 | ** Parameters: 376 | ** hdr -- NULL-terminated contents of an Authentication-Results: 377 | ** header field 378 | ** ar -- a pointer to a (struct authres) loaded by values after parsing 379 | ** 380 | ** Return value: 381 | ** 0 on success, -1 on failure. 382 | */ 383 | 384 | int 385 | ares_parse(u_char *hdr, struct authres *ar) 386 | { 387 | int n; 388 | int ntoks; 389 | int c; 390 | int r = 0; 391 | int state; 392 | int prevstate; 393 | u_char tmp[ARC_MAXHEADER + 2]; 394 | u_char *tokens[ARES_MAXTOKENS]; 395 | 396 | assert(hdr != NULL); 397 | assert(ar != NULL); 398 | 399 | memset(ar, '\0', sizeof *ar); 400 | memset(tmp, '\0', sizeof tmp); 401 | 402 | ntoks = ares_tokenize(hdr, tmp, sizeof tmp, tokens, ARES_MAXTOKENS); 403 | if (ntoks == -1 || ntoks > ARES_MAXTOKENS) 404 | return -1; 405 | 406 | prevstate = -1; 407 | state = 0; 408 | n = 0; 409 | 410 | for (c = 0; c < ntoks; c++) 411 | { 412 | if (tokens[c][0] == '(') /* comment */ 413 | { 414 | strlcpy((char *) ar->ares_result[n - 1].result_comment, 415 | (char *) tokens[c], 416 | sizeof ar->ares_result[n - 1].result_comment); 417 | continue; 418 | } 419 | 420 | switch (state) 421 | { 422 | case 0: /* authserv-id */ 423 | if (!isascii(tokens[c][0]) || 424 | !isalnum(tokens[c][0])) 425 | return -1; 426 | 427 | if (tokens[c][0] == ';') 428 | { 429 | prevstate = state; 430 | state = 3; 431 | } 432 | else 433 | { 434 | strlcat((char *) ar->ares_host, 435 | (char *) tokens[c], 436 | sizeof ar->ares_host); 437 | 438 | prevstate = state; 439 | state = 1; 440 | } 441 | 442 | break; 443 | 444 | case 1: /* [version] */ 445 | if (tokens[c][0] == '.' && 446 | tokens[c][1] == '\0' && prevstate == 0) 447 | { 448 | strlcat((char *) ar->ares_host, 449 | (char *) tokens[c], 450 | sizeof ar->ares_host); 451 | 452 | prevstate = state; 453 | state = 0; 454 | 455 | break; 456 | } 457 | 458 | if (tokens[c][0] == ';') 459 | { 460 | prevstate = state; 461 | state = 3; 462 | } 463 | else if (isascii(tokens[c][0]) && 464 | isdigit(tokens[c][0])) 465 | { 466 | strlcpy((char *) ar->ares_version, 467 | (char *) tokens[c], 468 | sizeof ar->ares_version); 469 | 470 | prevstate = state; 471 | state = 2; 472 | } 473 | else 474 | { 475 | return -1; 476 | } 477 | 478 | break; 479 | 480 | case 2: /* ; */ 481 | if (tokens[c][0] != ';' || 482 | tokens[c][1] != '\0') 483 | return -1; 484 | 485 | prevstate = state; 486 | state = 3; 487 | 488 | break; 489 | 490 | case 3: /* method/none */ 491 | if (n == 0 || !ares_dedup(ar, n)) 492 | n++; 493 | 494 | if (n >= MAXARESULTS) 495 | return 0; 496 | 497 | r = 0; 498 | 499 | if (strcasecmp((char *) tokens[c], "none") == 0) 500 | { 501 | if (n > 0) 502 | n--; 503 | 504 | prevstate = state; 505 | state = 14; 506 | 507 | continue; 508 | } 509 | 510 | ar->ares_result[n - 1].result_method = ares_convert(methods, 511 | (char *) tokens[c]); 512 | prevstate = state; 513 | state = 4; 514 | 515 | break; 516 | 517 | case 4: /* = */ 518 | if (tokens[c][0] != '=' || 519 | tokens[c][1] != '\0') 520 | return -1; 521 | 522 | prevstate = state; 523 | state = 5; 524 | 525 | break; 526 | 527 | case 5: /* result */ 528 | ar->ares_result[n - 1].result_result = ares_convert(aresults, 529 | (char *) tokens[c]); 530 | ar->ares_result[n - 1].result_comment[0] = '\0'; 531 | prevstate = state; 532 | state = 6; 533 | 534 | break; 535 | 536 | case 7: /* = (reason) */ 537 | if (tokens[c][0] != '=' || 538 | tokens[c][1] != '\0') 539 | return -1; 540 | 541 | prevstate = state; 542 | state = 8; 543 | 544 | break; 545 | 546 | case 8: 547 | strlcpy((char *) ar->ares_result[n - 1].result_reason, 548 | (char *) tokens[c], 549 | sizeof ar->ares_result[n - 1].result_reason); 550 | 551 | prevstate = state; 552 | state = 9; 553 | 554 | break; 555 | 556 | case 6: /* reason/propspec */ 557 | if (tokens[c][0] == ';' && /* neither */ 558 | tokens[c][1] == '\0') 559 | { 560 | prevstate = state; 561 | state = 3; 562 | 563 | continue; 564 | } 565 | 566 | if (strcasecmp((char *) tokens[c], "reason") == 0) 567 | { /* reason */ 568 | prevstate = state; 569 | state = 7; 570 | 571 | continue; 572 | } 573 | else 574 | { 575 | prevstate = state; 576 | state = 9; 577 | } 578 | 579 | /* FALLTHROUGH */ 580 | 581 | case 9: /* ptype */ 582 | if (prevstate == 13 && 583 | strchr(ARES_TOKENS2, tokens[c][0]) != NULL && 584 | tokens[c][1] == '\0') 585 | { 586 | r--; 587 | 588 | strlcat((char *) ar->ares_result[n - 1].result_value[r], 589 | (char *) tokens[c], 590 | sizeof ar->ares_result[n - 1].result_value[r]); 591 | 592 | prevstate = state; 593 | state = 13; 594 | 595 | continue; 596 | } 597 | 598 | if (tokens[c][0] == ';' && 599 | tokens[c][1] == '\0') 600 | { 601 | prevstate = state; 602 | state = 3; 603 | 604 | continue; 605 | } 606 | else 607 | { 608 | ares_ptype_t x; 609 | 610 | x = ares_convert(ptypes, (char *) tokens[c]); 611 | if (x == ARES_PTYPE_UNKNOWN) 612 | return -1; 613 | 614 | if (r < MAXPROPS) 615 | ar->ares_result[n - 1].result_ptype[r] = x; 616 | 617 | prevstate = state; 618 | state = 10; 619 | } 620 | 621 | break; 622 | 623 | case 10: /* . */ 624 | if (tokens[c][0] != '.' || 625 | tokens[c][1] != '\0') 626 | return -1; 627 | 628 | prevstate = state; 629 | state = 11; 630 | 631 | break; 632 | 633 | case 11: /* property */ 634 | if (r < MAXPROPS) 635 | { 636 | strlcpy((char *) ar->ares_result[n - 1].result_property[r], 637 | (char *) tokens[c], 638 | sizeof ar->ares_result[n - 1].result_property[r]); 639 | } 640 | 641 | prevstate = state; 642 | state = 12; 643 | 644 | break; 645 | 646 | case 12: /* = */ 647 | if (tokens[c][0] != '=' || 648 | tokens[c][1] != '\0') 649 | return -1; 650 | 651 | prevstate = state; 652 | state = 13; 653 | 654 | break; 655 | 656 | case 13: /* value */ 657 | if (r < MAXPROPS) 658 | { 659 | strlcat((char *) ar->ares_result[n - 1].result_value[r], 660 | (char *) tokens[c], 661 | sizeof ar->ares_result[n - 1].result_value[r]); 662 | r++; 663 | ar->ares_result[n - 1].result_props = r; 664 | } 665 | 666 | prevstate = state; 667 | state = 9; 668 | 669 | break; 670 | 671 | case 14: /* only reached in case of a malformed A-R */ 672 | return -1; 673 | 674 | break; /* not reached, just to make some lint-like sw happy */ 675 | } 676 | } 677 | 678 | /* error out on non-terminal states */ 679 | if (state == 4 || state == 7 || state == 10 || 680 | state == 11 || state == 12) 681 | return -1; 682 | 683 | if (n > 1) 684 | { 685 | if (ares_dedup(ar, n - 1)) 686 | n--; 687 | } 688 | 689 | ar->ares_count = n; 690 | 691 | return 0; 692 | } 693 | 694 | /* 695 | ** ARES_GETMETHOD -- translate a method code to its name 696 | ** 697 | ** Parameters: 698 | ** method -- method to convert 699 | ** 700 | ** Return value: 701 | ** String matching the provided method, or NULL. 702 | */ 703 | 704 | const char * 705 | ares_getmethod(ares_method_t method) 706 | { 707 | return (const char *) ares_xconvert(methods, method); 708 | } 709 | 710 | /* 711 | ** ARES_GETRESULT -- translate a result code to its name 712 | ** 713 | ** Parameters: 714 | ** result -- result to convert 715 | ** 716 | ** Return value: 717 | ** String matching the provided result, or NULL. 718 | */ 719 | 720 | const char * 721 | ares_getresult(ares_result_t result) 722 | { 723 | return (const char *) ares_xconvert(aresults, result); 724 | } 725 | 726 | /* 727 | ** ARES_GETPTYPE -- translate a ptype code to its name 728 | ** 729 | ** Parameters: 730 | ** ptype -- ptype to convert 731 | ** 732 | ** Return value: 733 | ** String matching the provided ptype, or NULL. 734 | */ 735 | 736 | const char * 737 | ares_getptype(ares_ptype_t ptype) 738 | { 739 | return (const char *) ares_xconvert(ptypes, ptype); 740 | } 741 | 742 | #ifdef ARTEST 743 | /* 744 | ** MAIN -- program mainline 745 | ** 746 | ** Parameters: 747 | ** argc, argv -- the usual 748 | ** 749 | ** Return value: 750 | ** EX_USAGE or EX_OK 751 | */ 752 | 753 | # define NTOKENS 256 754 | 755 | int 756 | main(int argc, char **argv) 757 | { 758 | int c; 759 | int d; 760 | int status; 761 | char *p; 762 | char *progname; 763 | struct authres ar; 764 | u_char buf[1024]; 765 | u_char *toks[NTOKENS]; 766 | 767 | progname = (p = strrchr(argv[0], '/')) == NULL ? argv[0] : p + 1; 768 | 769 | if (argc != 2) 770 | { 771 | printf("%s: usage: %s header-value\n", progname, progname); 772 | return EX_USAGE; 773 | } 774 | 775 | c = ares_tokenize(argv[1], buf, sizeof buf, toks, NTOKENS); 776 | for (d = 0; d < c; d++) 777 | printf("token %d = '%s'\n", d, toks[d]); 778 | 779 | printf("\n"); 780 | 781 | status = ares_parse(argv[1], &ar); 782 | if (status == -1) 783 | { 784 | printf("%s: ares_parse() returned -1\n", progname); 785 | return EX_OK; 786 | } 787 | 788 | printf("%d result%s found\n", ar.ares_count, 789 | ar.ares_count == 1 ? "" : "s"); 790 | 791 | printf("authserv-id '%s'\n", ar.ares_host); 792 | printf("version '%s'\n", ar.ares_version); 793 | 794 | for (c = 0; c < ar.ares_count; c++) 795 | { 796 | printf("result #%d, %d propert%s\n", c, 797 | ar.ares_result[c].result_props, 798 | ar.ares_result[c].result_props == 1 ? "y" : "ies"); 799 | 800 | printf("\tmethod \"%s\"\n", 801 | ares_xconvert(methods, 802 | ar.ares_result[c].result_method)); 803 | printf("\tresult \"%s\"\n", 804 | ares_xconvert(aresults, 805 | ar.ares_result[c].result_result)); 806 | printf("\treason \"%s\"\n", ar.ares_result[c].result_reason); 807 | 808 | for (d = 0; d < ar.ares_result[c].result_props; d++) 809 | { 810 | printf("\tproperty #%d\n", d); 811 | printf("\t\tptype \"%s\"\n", 812 | ares_xconvert(ptypes, 813 | ar.ares_result[c].result_ptype[d])); 814 | printf("\t\tproperty \"%s\"\n", 815 | ar.ares_result[c].result_property[d]); 816 | printf("\t\tvalue \"%s\"\n", 817 | ar.ares_result[c].result_value[d]); 818 | } 819 | } 820 | } 821 | #endif /* ARTEST */ 822 | -------------------------------------------------------------------------------- /openarc/openarc-ar.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009, 2012-2014, 2016, 2017, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #ifndef _OPENARC_AR_H_ 10 | #define _OPENARC_AR_H_ 11 | 12 | /* system includes */ 13 | /* system includes */ 14 | #include 15 | 16 | /* openarc includes */ 17 | #include "openarc.h" 18 | 19 | /* limits */ 20 | #define MAXARESULTS 16 21 | #define MAXPROPS 16 22 | #define MAXAVALUE 256 23 | 24 | /* ARES_METHOD_T -- type for specifying an authentication method */ 25 | typedef int ares_method_t; 26 | 27 | #define ARES_METHOD_UNKNOWN (-1) 28 | #define ARES_METHOD_AUTH 0 29 | #define ARES_METHOD_DKIM 1 30 | #define ARES_METHOD_DOMAINKEYS 2 31 | #define ARES_METHOD_SENDERID 3 32 | #define ARES_METHOD_SPF 4 33 | #define ARES_METHOD_DKIMADSP 5 34 | #define ARES_METHOD_IPREV 6 35 | #define ARES_METHOD_DKIMATPS 7 36 | #define ARES_METHOD_DMARC 8 37 | #define ARES_METHOD_SMIME 9 38 | #define ARES_METHOD_RRVS 10 39 | #define ARES_METHOD_ARC 11 40 | 41 | /* ARES_RESULT_T -- type for specifying an authentication result */ 42 | typedef int ares_result_t; 43 | 44 | #define ARES_RESULT_UNDEFINED (-1) 45 | #define ARES_RESULT_PASS 0 46 | #define ARES_RESULT_UNASSIGNED 1 /* UNASSIGNED */ 47 | #define ARES_RESULT_SOFTFAIL 2 48 | #define ARES_RESULT_NEUTRAL 3 49 | #define ARES_RESULT_TEMPERROR 4 50 | #define ARES_RESULT_PERMERROR 5 51 | #define ARES_RESULT_NONE 6 52 | #define ARES_RESULT_FAIL 7 53 | #define ARES_RESULT_POLICY 8 54 | #define ARES_RESULT_NXDOMAIN 9 55 | #define ARES_RESULT_SIGNED 10 56 | #define ARES_RESULT_UNKNOWN 11 57 | #define ARES_RESULT_DISCARD 12 58 | 59 | /* ARES_PTYPE_T -- type for specifying an authentication property */ 60 | typedef int ares_ptype_t; 61 | 62 | #define ARES_PTYPE_UNKNOWN (-1) 63 | #define ARES_PTYPE_SMTP 0 64 | #define ARES_PTYPE_HEADER 1 65 | #define ARES_PTYPE_BODY 2 66 | #define ARES_PTYPE_POLICY 3 67 | 68 | /* RESULT structure -- a single result */ 69 | struct result 70 | { 71 | int result_props; 72 | ares_method_t result_method; 73 | ares_result_t result_result; 74 | ares_ptype_t result_ptype[MAXPROPS]; 75 | unsigned char result_reason[MAXAVALUE + 1]; 76 | unsigned char result_comment[MAXAVALUE + 1]; 77 | unsigned char result_property[MAXPROPS][MAXAVALUE + 1]; 78 | unsigned char result_value[MAXPROPS][MAXAVALUE + 1]; 79 | }; 80 | 81 | /* AUTHRES structure -- the entire header parsed */ 82 | struct authres 83 | { 84 | int ares_count; 85 | unsigned char ares_host[ARC_MAXHOSTNAMELEN + 1]; 86 | unsigned char ares_version[MAXAVALUE + 1]; 87 | struct result ares_result[MAXARESULTS]; 88 | }; 89 | 90 | /* 91 | ** ARES_PARSE -- parse an Authentication-Results: header, return a 92 | ** structure containing a parsed result 93 | ** 94 | ** Parameters: 95 | ** hdr -- NULL-terminated contents of an Authentication-Results: 96 | ** header field 97 | ** ar -- a pointer to a (struct authres) loaded by values after parsing 98 | ** 99 | ** Return value: 100 | ** 0 on success, -1 on failure. 101 | */ 102 | 103 | extern int ares_parse __P((u_char *, struct authres *)); 104 | 105 | extern const char *ares_getmethod __P((ares_method_t)); 106 | extern const char *ares_getresult __P((ares_result_t)); 107 | extern const char *ares_getptype __P((ares_ptype_t)); 108 | 109 | #endif /* _OPENARC_AR_H_ */ 110 | -------------------------------------------------------------------------------- /openarc/openarc-config.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, 2017, The Trusted Domain Project. All rights reserved. 3 | */ 4 | 5 | #ifndef _ARC_CONFIG_H_ 6 | #define _ARC_CONFIG_H_ 7 | 8 | #include "build-config.h" 9 | 10 | /* system includes */ 11 | #include 12 | 13 | /* macros */ 14 | #ifndef FALSE 15 | # define FALSE 0 16 | #endif /* ! FALSE */ 17 | #ifndef TRUE 18 | # define TRUE 1 19 | #endif /* ! TRUE */ 20 | 21 | /* config definition */ 22 | struct configdef arcf_config[] = 23 | { 24 | { "AuthservID", CONFIG_TYPE_STRING, FALSE }, 25 | { "AutoRestart", CONFIG_TYPE_BOOLEAN, FALSE }, 26 | { "AutoRestartCount", CONFIG_TYPE_INTEGER, FALSE }, 27 | { "AutoRestartRate", CONFIG_TYPE_STRING, FALSE }, 28 | { "Background", CONFIG_TYPE_BOOLEAN, FALSE }, 29 | { "BaseDirectory", CONFIG_TYPE_STRING, FALSE }, 30 | { "Canonicalization", CONFIG_TYPE_STRING, FALSE }, 31 | { "ChangeRootDirectory", CONFIG_TYPE_STRING, FALSE }, 32 | { "Domain", CONFIG_TYPE_STRING, TRUE }, 33 | { "EnableCoredumps", CONFIG_TYPE_BOOLEAN, FALSE }, 34 | { "FixedTimestamp", CONFIG_TYPE_STRING, FALSE }, 35 | { "Include", CONFIG_TYPE_INCLUDE, FALSE }, 36 | { "InternalHosts", CONFIG_TYPE_STRING, FALSE }, 37 | { "KeepTemporaryFiles", CONFIG_TYPE_BOOLEAN, FALSE }, 38 | { "KeyFile", CONFIG_TYPE_STRING, TRUE }, 39 | { "MaximumHeaders", CONFIG_TYPE_INTEGER, FALSE }, 40 | { "MilterDebug", CONFIG_TYPE_INTEGER, FALSE }, 41 | { "Mode", CONFIG_TYPE_STRING, FALSE }, 42 | { "PeerList", CONFIG_TYPE_STRING, FALSE }, 43 | { "PidFile", CONFIG_TYPE_STRING, FALSE }, 44 | { "Selector", CONFIG_TYPE_STRING, TRUE }, 45 | { "SignatureAlgorithm", CONFIG_TYPE_STRING, FALSE }, 46 | { "SignHeaders", CONFIG_TYPE_STRING, FALSE }, 47 | { "OverSignHeaders", CONFIG_TYPE_STRING, FALSE }, 48 | { "Socket", CONFIG_TYPE_STRING, FALSE }, 49 | { "SoftwareHeader", CONFIG_TYPE_BOOLEAN, FALSE }, 50 | { "Syslog", CONFIG_TYPE_BOOLEAN, FALSE }, 51 | { "SyslogFacility", CONFIG_TYPE_STRING, FALSE }, 52 | { "TemporaryDirectory", CONFIG_TYPE_STRING, FALSE }, 53 | { "UserID", CONFIG_TYPE_STRING, FALSE }, 54 | { NULL, (u_int) -1, FALSE } 55 | }; 56 | 57 | #endif /* _ARC_CONFIG_H_ */ 58 | -------------------------------------------------------------------------------- /openarc/openarc-crypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, 2017, The Trusted Domain Project. 3 | ** All rights reserved. 4 | */ 5 | 6 | #include 7 | 8 | #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) 9 | 10 | #include "build-config.h" 11 | 12 | /* system includes */ 13 | #include 14 | #ifdef HAVE_STDBOOL_H 15 | # include 16 | #endif /* HAVE_STDBOOL_H */ 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | /* openssl includes */ 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | /* openarc includes */ 31 | #include "openarc-crypto.h" 32 | #include "openarc.h" 33 | 34 | /* globals */ 35 | static _Bool crypto_init_done = FALSE; 36 | static pthread_mutex_t id_lock; 37 | static pthread_key_t id_key; 38 | static unsigned int nmutexes = 0; 39 | static unsigned long threadid = 0L; 40 | static pthread_mutex_t *mutexes = NULL; 41 | 42 | /* 43 | ** ARCF_CRYPTO_LOCK_CALLBACK -- locking callback for libcrypto 44 | ** 45 | ** Parameters: 46 | ** mode -- lock mode (request from libcrypto) 47 | ** idx -- lock index for this request 48 | ** file -- file making the request 49 | ** line -- line making the request 50 | ** 51 | ** Return value: 52 | ** None. 53 | */ 54 | 55 | static void 56 | arcf_crypto_lock_callback(int mode, int idx, 57 | /* UNUSED */ const char *file, 58 | /* UNUSED */ int line) 59 | { 60 | int status; 61 | 62 | if ((mode & CRYPTO_LOCK) != 0) 63 | status = pthread_mutex_lock(&mutexes[idx]); 64 | else 65 | status = pthread_mutex_unlock(&mutexes[idx]); 66 | 67 | assert(status == 0); 68 | } 69 | 70 | /* 71 | ** ARCF_CRYPTO_GET_ID -- generate/retrieve thread ID 72 | ** 73 | ** Parameters: 74 | ** 75 | ** Return value: 76 | ** 77 | */ 78 | 79 | static unsigned long 80 | arcf_crypto_get_id(void) 81 | { 82 | unsigned long *id; 83 | 84 | id = pthread_getspecific(id_key); 85 | if (id == NULL) 86 | { 87 | id = (unsigned long *) malloc(sizeof *id); 88 | assert(pthread_mutex_lock(&id_lock) == 0); 89 | threadid++; 90 | *id = threadid; 91 | assert(pthread_mutex_unlock(&id_lock) == 0); 92 | assert(pthread_setspecific(id_key, id) == 0); 93 | } 94 | 95 | return *id; 96 | } 97 | 98 | /* 99 | ** ARCF_CRYPTO_FREE_ID -- destroy thread ID 100 | ** 101 | ** Parameters: 102 | ** ptr -- pointer to be destroyed 103 | ** 104 | ** Return value: 105 | ** None. 106 | */ 107 | 108 | static void 109 | arcf_crypto_free_id(void *ptr) 110 | { 111 | /* 112 | ** Trick arcf_crypto_get_id(); the thread-specific pointer has 113 | ** already been cleared at this point, but arcf_crypto_get_id() 114 | ** may be called by ERR_remove_state() which will then allocate a 115 | ** new thread pointer if the thread-specific pointer is NULL. This 116 | ** means a memory leak of thread IDs and, on Solaris, an infinite loop 117 | ** because the destructor (indirectly) re-sets the thread-specific 118 | ** pointer to something not NULL. See pthread_key_create(3). 119 | */ 120 | 121 | if (ptr != NULL) 122 | { 123 | assert(pthread_setspecific(id_key, ptr) == 0); 124 | 125 | ERR_remove_state(0); 126 | 127 | free(ptr); 128 | 129 | /* now we can actually clear it for real */ 130 | assert(pthread_setspecific(id_key, NULL) == 0); 131 | } 132 | } 133 | 134 | /* 135 | ** ARCF_CRYPTO_DYN_CREATE -- dynamically create a mutex 136 | ** 137 | ** Parameters: 138 | ** file -- file making the request 139 | ** line -- line making the request 140 | ** 141 | ** Return value: 142 | ** Pointer to the new mutex. 143 | */ 144 | 145 | static struct CRYPTO_dynlock_value * 146 | arcf_crypto_dyn_create(/* UNUSED */ const char *file, 147 | /* UNUSED */ int line) 148 | { 149 | int err; 150 | pthread_mutex_t *new; 151 | 152 | new = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); 153 | if (new == NULL) 154 | return NULL; 155 | 156 | err = pthread_mutex_init(new, NULL); 157 | if (err != 0) 158 | { 159 | free(new); 160 | return NULL; 161 | } 162 | 163 | return (void *) new; 164 | } 165 | 166 | /* 167 | ** ARCF_CRYPTO_DYN_DESTROY -- destroy a dynamic mutex 168 | ** 169 | ** Parameters: 170 | ** mutex -- pointer to the mutex to destroy 171 | ** file -- file making the request 172 | ** line -- line making the request 173 | ** 174 | ** Return value: 175 | ** None. 176 | */ 177 | 178 | static void 179 | arcf_crypto_dyn_destroy(struct CRYPTO_dynlock_value *lock, 180 | /* UNUSED */ const char *file, 181 | /* UNUSED */ int line) 182 | { 183 | assert(lock != NULL); 184 | 185 | pthread_mutex_destroy((pthread_mutex_t *) lock); 186 | 187 | free(lock); 188 | } 189 | 190 | /* 191 | ** ARCF_CRYPTO_DYN_LOCK -- lock/unlock a dynamic mutex 192 | ** 193 | ** Parameters: 194 | ** mode -- lock mode (request from libcrypto) 195 | ** mutex -- pointer to the mutex to lock/unlock 196 | ** file -- file making the request 197 | ** line -- line making the request 198 | ** 199 | ** Return value: 200 | ** None. 201 | */ 202 | 203 | static void 204 | arcf_crypto_dyn_lock(int mode, struct CRYPTO_dynlock_value *lock, 205 | /* UNUSED */ const char *file, 206 | /* UNUSED */ int line) 207 | { 208 | int status; 209 | 210 | assert(lock != NULL); 211 | 212 | if ((mode & CRYPTO_LOCK) != 0) 213 | status = pthread_mutex_lock((pthread_mutex_t *) lock); 214 | else 215 | status = pthread_mutex_unlock((pthread_mutex_t *) lock); 216 | 217 | assert(status == 0); 218 | } 219 | 220 | /* 221 | ** ARCF_CRYPTO_INIT -- set up openssl dependencies 222 | ** 223 | ** Parameters: 224 | ** None. 225 | ** 226 | ** Return value: 227 | ** 0 -- success 228 | ** !0 -- an error code (a la errno) 229 | */ 230 | 231 | int 232 | arcf_crypto_init(void) 233 | { 234 | int c; 235 | int n; 236 | int status; 237 | 238 | n = CRYPTO_num_locks(); 239 | mutexes = (pthread_mutex_t *) malloc(n * sizeof(pthread_mutex_t)); 240 | if (mutexes == NULL) 241 | return errno; 242 | 243 | for (c = 0; c < n; c++) 244 | { 245 | status = pthread_mutex_init(&mutexes[c], NULL); 246 | if (status != 0) 247 | return status; 248 | } 249 | 250 | status = pthread_mutex_init(&id_lock, NULL); 251 | if (status != 0) 252 | return status; 253 | 254 | nmutexes = n; 255 | 256 | status = pthread_key_create(&id_key, &arcf_crypto_free_id); 257 | if (status != 0) 258 | return status; 259 | 260 | SSL_load_error_strings(); 261 | SSL_library_init(); 262 | ERR_load_crypto_strings(); 263 | 264 | CRYPTO_set_id_callback(&arcf_crypto_get_id); 265 | CRYPTO_set_locking_callback(&arcf_crypto_lock_callback); 266 | CRYPTO_set_dynlock_create_callback(&arcf_crypto_dyn_create); 267 | CRYPTO_set_dynlock_lock_callback(&arcf_crypto_dyn_lock); 268 | CRYPTO_set_dynlock_destroy_callback(&arcf_crypto_dyn_destroy); 269 | 270 | #ifdef USE_OPENSSL_ENGINE 271 | if (!SSL_set_engine(NULL)) 272 | return EINVAL; 273 | #endif /* USE_OPENSSL_ENGINE */ 274 | 275 | crypto_init_done = TRUE; 276 | 277 | return 0; 278 | } 279 | 280 | /* 281 | ** ARCF_CRYPTO_FREE -- tear down openssl dependencies 282 | ** 283 | ** Parameters: 284 | ** None. 285 | ** 286 | ** Return value: 287 | ** None. 288 | */ 289 | 290 | void 291 | arcf_crypto_free(void) 292 | { 293 | if (crypto_init_done) 294 | { 295 | CRYPTO_cleanup_all_ex_data(); 296 | CONF_modules_free(); 297 | EVP_cleanup(); 298 | ERR_free_strings(); 299 | ERR_remove_state(0); 300 | 301 | if (nmutexes > 0) 302 | { 303 | unsigned int c; 304 | 305 | for (c = 0; c < nmutexes; c++) 306 | pthread_mutex_destroy(&mutexes[c]); 307 | 308 | free(mutexes); 309 | mutexes = NULL; 310 | nmutexes = 0; 311 | } 312 | 313 | crypto_init_done = FALSE; 314 | } 315 | } 316 | 317 | #endif /* OpenSSL < 1.1.0 */ 318 | -------------------------------------------------------------------------------- /openarc/openarc-crypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, The Trusted Domain Project. All rights reserved. 3 | ** 4 | */ 5 | 6 | #ifndef _ARC_CRYPTO_H_ 7 | #define _ARC_CRYPTO_H_ 8 | 9 | #ifdef __STDC__ 10 | # ifndef __P 11 | # define __P(x) x 12 | # endif /* ! __P */ 13 | #else /* __STDC__ */ 14 | # ifndef __P 15 | # define __P(x) () 16 | # endif /* ! __P */ 17 | #endif /* __STDC__ */ 18 | 19 | /* PROTOTYPES */ 20 | extern int arcf_crypto_init __P((void)); 21 | extern void arcf_crypto_free __P((void)); 22 | 23 | #endif /* _ARC_CRYPTO_H_ */ 24 | -------------------------------------------------------------------------------- /openarc/openarc-test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2007-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2013, The Trusted Domain Project. All rights reserved. 6 | */ 7 | 8 | /* system includes */ 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /* libopenarc includes */ 21 | #include "build-config.h" 22 | #include 23 | 24 | /* libbsd if found */ 25 | #ifdef USE_BSD_H 26 | # include 27 | #endif /* USE_BSD_H */ 28 | 29 | /* libstrl if needed */ 30 | #ifdef USE_STRL_H 31 | # include 32 | #endif /* USE_STRL_H */ 33 | 34 | /* libmilter includes */ 35 | #include 36 | 37 | /* openarc includes */ 38 | #define ARCF_MILTER_PROTOTYPES 39 | #include "openarc-test.h" 40 | #include "openarc.h" 41 | 42 | /* local types and definitions*/ 43 | #define CRLF "\r\n" 44 | 45 | struct test_context 46 | { 47 | void * tc_priv; /* private data pointer */ 48 | }; 49 | 50 | char *milter_status[] = 51 | { 52 | "SMFIS_CONTINUE", 53 | "SMFIS_REJECT", 54 | "SMFIS_DISCARD", 55 | "SMFIS_ACCEPT", 56 | "SMFIS_TEMPFAIL" 57 | }; 58 | 59 | char *envfrom[] = 60 | { 61 | "", 62 | NULL 63 | }; 64 | 65 | #define FCLOSE(x) if ((x) != stdin) \ 66 | fclose((x)); 67 | #define MLFI_OUTPUT(x,y) ((y) > 1 || ((y) == 1 && (x) != SMFIS_CONTINUE)) 68 | #define STRORNULL(x) ((x) == NULL ? "(null)" : (x)) 69 | 70 | /* globals */ 71 | static int tverbose = 0; 72 | 73 | /* 74 | ** ARCF_TEST_SETPRIV -- store private pointer 75 | ** 76 | ** Parameters: 77 | ** ctx -- context pointer 78 | ** ptr -- pointer to store 79 | ** 80 | ** Return value: 81 | ** MI_SUCCESS 82 | */ 83 | 84 | int 85 | arcf_test_setpriv(void *ctx, void *ptr) 86 | { 87 | struct test_context *tc; 88 | 89 | assert(ctx != NULL); 90 | 91 | tc = ctx; 92 | tc->tc_priv = ptr; 93 | 94 | return MI_SUCCESS; 95 | } 96 | 97 | /* 98 | ** ARCF_TEST_GETPRIV -- retrieve private pointer 99 | ** 100 | ** Parameters: 101 | ** ctx -- context pointer 102 | ** 103 | ** Return value: 104 | ** The private pointer. 105 | */ 106 | 107 | void * 108 | arcf_test_getpriv(void *ctx) 109 | { 110 | struct test_context *tc; 111 | 112 | assert(ctx != NULL); 113 | 114 | tc = ctx; 115 | 116 | return tc->tc_priv; 117 | } 118 | 119 | /* 120 | ** ARCF_TEST_PROGRESS -- send progress message 121 | ** 122 | ** Parameters: 123 | ** ctx -- context pointer 124 | ** 125 | ** Return value: 126 | ** MI_SUCCESS 127 | */ 128 | 129 | int 130 | arcf_test_progress(void *ctx) 131 | { 132 | assert(ctx != NULL); 133 | 134 | if (tverbose > 1) 135 | fprintf(stdout, "### PROGRESS\n"); 136 | 137 | return MI_SUCCESS; 138 | } 139 | 140 | /* 141 | ** ARCF_TEST_SETREPLY -- set reply to use 142 | ** 143 | ** Parameters: 144 | ** ctx -- context pointer 145 | ** rcode -- SMTP reply code 146 | ** xcode -- SMTP enhanced reply code 147 | ** replytxt -- SMTP reply text 148 | ** 149 | ** Return value: 150 | ** MI_SUCCESS 151 | */ 152 | 153 | int 154 | arcf_test_setreply(void *ctx, char *rcode, char *xcode, char *replytxt) 155 | { 156 | assert(ctx != NULL); 157 | 158 | if (tverbose > 1) 159 | { 160 | fprintf(stdout, 161 | "### SETREPLY: rcode='%s' xcode='%s' replytxt='%s'\n", 162 | STRORNULL(rcode), STRORNULL(xcode), 163 | STRORNULL(replytxt)); 164 | } 165 | 166 | return MI_SUCCESS; 167 | } 168 | 169 | /* 170 | ** ARCF_TEST_INSHEADER -- insert a header 171 | ** 172 | ** Parameters: 173 | ** ctx -- context pointer 174 | ** idx -- insertion index 175 | ** hname -- header name 176 | ** hvalue -- header value 177 | ** 178 | ** Return value: 179 | ** MI_SUCCESS 180 | */ 181 | 182 | int 183 | arcf_test_insheader(void *ctx, int idx, char *hname, char *hvalue) 184 | { 185 | assert(ctx != NULL); 186 | 187 | if (tverbose > 1) 188 | { 189 | fprintf(stdout, 190 | "### INSHEADER: idx=%d hname='%s' hvalue='%s'\n", 191 | idx, STRORNULL(hname), STRORNULL(hvalue)); 192 | } 193 | 194 | return MI_SUCCESS; 195 | } 196 | 197 | /* 198 | ** ARCF_TEST_CHGHEADER -- change a header 199 | ** 200 | ** Parameters: 201 | ** ctx -- context pointer 202 | ** hname -- header name 203 | ** idx -- header index 204 | ** hvalue -- header value 205 | ** 206 | ** Return value: 207 | ** MI_SUCCESS 208 | */ 209 | 210 | int 211 | arcf_test_chgheader(void *ctx, char *hname, int idx, char *hvalue) 212 | { 213 | assert(ctx != NULL); 214 | 215 | if (tverbose > 1) 216 | { 217 | fprintf(stdout, 218 | "### CHGHEADER: hname='%s' idx=%d hvalue='%s'\n", 219 | STRORNULL(hname), idx, STRORNULL(hvalue)); 220 | } 221 | 222 | return MI_SUCCESS; 223 | } 224 | 225 | /* 226 | ** ARCF_TEST_QUARANTINE -- request message quarantine 227 | ** 228 | ** Parameters: 229 | ** ctx -- context pointer 230 | ** reason -- reason string 231 | ** 232 | ** Return value: 233 | ** MI_SUCCESS 234 | */ 235 | 236 | int 237 | arcf_test_quarantine(void *ctx, char *reason) 238 | { 239 | assert(ctx != NULL); 240 | 241 | if (tverbose > 1) 242 | { 243 | fprintf(stdout, 244 | "### QUARANTINE: reason='%s'\n", STRORNULL(reason)); 245 | } 246 | 247 | return MI_SUCCESS; 248 | } 249 | 250 | /* 251 | ** ARCF_TEST_ADDHEADER -- append a header 252 | ** 253 | ** Parameters: 254 | ** ctx -- context pointer 255 | ** hname -- header name 256 | ** hvalue -- header value 257 | ** 258 | ** Return value: 259 | ** MI_SUCCESS 260 | */ 261 | 262 | int 263 | arcf_test_addheader(void *ctx, char *hname, char *hvalue) 264 | { 265 | assert(ctx != NULL); 266 | 267 | if (tverbose > 1) 268 | { 269 | fprintf(stdout, 270 | "### ADDHEADER: hname='%s' hvalue='%s'\n", 271 | STRORNULL(hname), STRORNULL(hvalue)); 272 | } 273 | 274 | return MI_SUCCESS; 275 | } 276 | 277 | /* 278 | ** ARCF_TEST_DELRCPT -- request recipient delete 279 | ** 280 | ** Parameters: 281 | ** ctx -- context pointer 282 | ** addr -- address 283 | ** 284 | ** Return value: 285 | ** MI_SUCCESS 286 | */ 287 | 288 | int 289 | arcf_test_delrcpt(void *ctx, char *addr) 290 | { 291 | assert(ctx != NULL); 292 | assert(addr != NULL); 293 | 294 | if (tverbose > 1) 295 | fprintf(stdout, "### DELRCPT: '%s'\n", addr); 296 | 297 | return MI_SUCCESS; 298 | } 299 | 300 | /* 301 | ** ARCF_TEST_ADDRCPT -- request recipient add 302 | ** 303 | ** Parameters: 304 | ** ctx -- context pointer 305 | ** addr -- address 306 | ** 307 | ** Return value: 308 | ** MI_SUCCESS 309 | */ 310 | 311 | int 312 | arcf_test_addrcpt(void *ctx, char *addr) 313 | { 314 | assert(ctx != NULL); 315 | assert(addr != NULL); 316 | 317 | if (tverbose > 1) 318 | fprintf(stdout, "### ADDRCPT: '%s'\n", addr); 319 | 320 | return MI_SUCCESS; 321 | } 322 | 323 | /* 324 | ** ARCF_TEST_GETSYMVAL -- retrieve a symbol value 325 | ** 326 | ** Parameters: 327 | ** ctx -- context pointer 328 | ** sym -- symbol name 329 | ** 330 | ** Return value: 331 | ** Pointer to (static) string name. 332 | ** 333 | ** Note: 334 | ** This isn't thread-safe, but test mode is single-threaded anyway. 335 | ** This is also a memory leak, but it's a short-lived test program 336 | ** anyway. 337 | */ 338 | 339 | char * 340 | arcf_test_getsymval(void *ctx, char *sym) 341 | { 342 | static char symout[MAXBUFRSZ]; 343 | 344 | assert(ctx != NULL); 345 | assert(sym != NULL); 346 | 347 | snprintf(symout, sizeof symout, "DEBUG-%s", sym); 348 | 349 | return strdup(symout); 350 | } 351 | 352 | /* 353 | ** ARCF_TESTFILE -- read a message and test it 354 | ** 355 | ** Parameters: 356 | ** libopenarc -- DKIM_LIB handle 357 | ** file -- input file path 358 | ** fixedtime -- time to use on signatures (or -1) 359 | ** verbose -- verbose level 360 | ** 361 | ** Return value: 362 | ** An EX_* constant (see sysexits.h) 363 | */ 364 | 365 | static int 366 | arcf_testfile(ARC_LIB *libopenarc, struct test_context *tctx, 367 | FILE *f, char *file, int tverbose) 368 | { 369 | bool inheaders = TRUE; 370 | int len = 0; 371 | int buflen = 0; 372 | int lineno = 0; 373 | int hslineno = 0; 374 | int c; 375 | ARC_MESSAGE *msg; 376 | char *p; 377 | sfsistat ms; 378 | char buf[MAXBUFRSZ]; 379 | char line[MAXBUFRSZ]; 380 | 381 | assert(libopenarc != NULL); 382 | assert(tctx != NULL); 383 | assert(f != NULL); 384 | 385 | memset(buf, '\0', sizeof buf); 386 | memset(line, '\0', sizeof buf); 387 | 388 | ms = mlfi_envfrom((SMFICTX *) tctx, envfrom); 389 | if (MLFI_OUTPUT(ms, tverbose)) 390 | { 391 | fprintf(stderr, "%s: %s: mlfi_envfrom() returned %s\n", 392 | progname, file, milter_status[ms]); 393 | } 394 | if (ms != SMFIS_CONTINUE) 395 | return EX_SOFTWARE; 396 | 397 | while (!feof(f)) 398 | { 399 | if (fgets(line, sizeof line, f) == NULL) 400 | break; 401 | 402 | lineno++; 403 | 404 | c = '\0'; 405 | for (p = line; *p != '\0'; p++) 406 | { 407 | if (*p == '\n') 408 | { 409 | *p = '\0'; 410 | break; 411 | } 412 | 413 | c = *p; 414 | } 415 | 416 | if (c == '\r' && p != line) /* eat the CR */ 417 | *(p - 1) = '\0'; 418 | 419 | if (inheaders) 420 | { 421 | if (line[0] == '\0') 422 | { 423 | if (buf[0] != '\0') 424 | { 425 | char *colon; 426 | 427 | colon = strchr(buf, ':'); 428 | if (colon == NULL) 429 | { 430 | fprintf(stderr, 431 | "%s: %s: line %d: header malformed\n", 432 | progname, file, 433 | lineno); 434 | return EX_DATAERR; 435 | } 436 | 437 | *colon = '\0'; 438 | if (*(colon + 1) == ' ') 439 | colon++; 440 | 441 | ms = mlfi_header((SMFICTX *) tctx, buf, 442 | colon + 1); 443 | if (MLFI_OUTPUT(ms, tverbose)) 444 | { 445 | fprintf(stderr, 446 | "%s: %s: line %d: mlfi_header() returned %s\n", 447 | progname, file, 448 | hslineno, 449 | milter_status[ms]); 450 | } 451 | 452 | if (ms != SMFIS_CONTINUE) 453 | return EX_SOFTWARE; 454 | } 455 | 456 | inheaders = FALSE; 457 | memset(buf, '\0', sizeof buf); 458 | memset(line, '\0', sizeof buf); 459 | 460 | ms = mlfi_eoh((SMFICTX *) tctx); 461 | if (MLFI_OUTPUT(ms, tverbose)) 462 | { 463 | fprintf(stderr, 464 | "%s: %s: mlfi_eoh() returned %s\n", 465 | progname, file, 466 | milter_status[ms]); 467 | } 468 | if (ms != SMFIS_CONTINUE) 469 | return EX_SOFTWARE; 470 | 471 | continue; 472 | } 473 | 474 | if (line[0] == ' ' || line[0] == '\t') 475 | { 476 | (void) strlcat(buf, CRLF, sizeof buf); 477 | 478 | if (strlcat(buf, line, 479 | sizeof buf) >= sizeof buf) 480 | { 481 | fprintf(stderr, 482 | "%s: %s: line %d: header '%*s...' too large\n", 483 | progname, file, lineno, 484 | 20, buf); 485 | return EX_DATAERR; 486 | } 487 | } 488 | else 489 | { 490 | if (buf[0] != '\0') 491 | { 492 | char *colon; 493 | 494 | colon = strchr(buf, ':'); 495 | if (colon == NULL) 496 | { 497 | fprintf(stderr, 498 | "%s: %s: line %d: header malformed\n", 499 | progname, file, 500 | lineno); 501 | return EX_DATAERR; 502 | } 503 | 504 | *colon = '\0'; 505 | if (*(colon + 1) == ' ') 506 | colon++; 507 | 508 | ms = mlfi_header((SMFICTX *) tctx, buf, 509 | colon + 1); 510 | if (MLFI_OUTPUT(ms, tverbose)) 511 | { 512 | fprintf(stderr, 513 | "%s: %s: line %d: mlfi_header() returned %s\n", 514 | progname, file, 515 | hslineno, 516 | milter_status[ms]); 517 | } 518 | if (ms != SMFIS_CONTINUE) 519 | return EX_SOFTWARE; 520 | hslineno = 0; 521 | } 522 | 523 | if (hslineno == 0) 524 | hslineno = lineno; 525 | 526 | strlcpy(buf, line, sizeof buf); 527 | } 528 | } 529 | else 530 | { 531 | len = strlen(line); 532 | 533 | if (len + buflen >= (int) sizeof buf - 3) 534 | { 535 | ms = mlfi_body((SMFICTX *) tctx, 536 | (u_char *) buf, 537 | strlen(buf)); 538 | if (MLFI_OUTPUT(ms, tverbose)) 539 | { 540 | fprintf(stderr, 541 | "%s: %s: mlfi_body() returned %s\n", 542 | progname, file, 543 | milter_status[ms]); 544 | } 545 | if (ms != SMFIS_CONTINUE) 546 | return EX_SOFTWARE; 547 | 548 | memset(buf, '\0', sizeof buf); 549 | buflen = 0; 550 | } 551 | 552 | memcpy(&buf[buflen], line, len); 553 | buflen += len; 554 | memcpy(&buf[buflen], CRLF, 2); 555 | buflen += 2; 556 | } 557 | } 558 | 559 | /* unprocessed partial header? */ 560 | if (inheaders && buf[0] != '\0') 561 | { 562 | char *colon; 563 | 564 | colon = strchr(buf, ':'); 565 | if (colon == NULL) 566 | { 567 | fprintf(stderr, 568 | "%s: %s: line %d: header malformed\n", 569 | progname, file, lineno); 570 | return EX_DATAERR; 571 | } 572 | 573 | *colon = '\0'; 574 | if (*(colon + 1) == ' ') 575 | colon++; 576 | 577 | ms = mlfi_header((SMFICTX *) tctx, buf, colon + 1); 578 | if (MLFI_OUTPUT(ms, tverbose)) 579 | { 580 | fprintf(stderr, 581 | "%s: %s: line %d: mlfi_header() returned %s\n", 582 | progname, file, lineno, milter_status[ms]); 583 | } 584 | if (ms != SMFIS_CONTINUE) 585 | return EX_SOFTWARE; 586 | 587 | ms = mlfi_eoh((SMFICTX *) tctx); 588 | if (MLFI_OUTPUT(ms, tverbose)) 589 | { 590 | fprintf(stderr, 591 | "%s: %s: mlfi_eoh() returned %s\n", 592 | progname, file, milter_status[ms]); 593 | } 594 | if (ms != SMFIS_CONTINUE) 595 | return EX_SOFTWARE; 596 | 597 | inheaders = FALSE; 598 | memset(buf, '\0', sizeof buf); 599 | } 600 | 601 | /* no headers found */ 602 | if (inheaders) 603 | { 604 | fprintf(stderr, "%s: %s: warning: no headers on input\n", 605 | progname, file); 606 | 607 | ms = mlfi_eoh((SMFICTX *) tctx); 608 | if (MLFI_OUTPUT(ms, tverbose)) 609 | { 610 | fprintf(stderr, "%s: %s: mlfi_eoh() returned %s\n", 611 | progname, file, milter_status[ms]); 612 | } 613 | if (ms != SMFIS_CONTINUE) 614 | return EX_SOFTWARE; 615 | } 616 | 617 | /* some body left */ 618 | if (!inheaders && buf[0] != '\0') 619 | { 620 | ms = mlfi_body((SMFICTX *) tctx, (u_char *) buf, strlen(buf)); 621 | if (MLFI_OUTPUT(ms, tverbose)) 622 | { 623 | fprintf(stderr, "%s: %s: mlfi_body() returned %s\n", 624 | progname, file, milter_status[ms]); 625 | } 626 | if (ms != SMFIS_CONTINUE) 627 | return EX_SOFTWARE; 628 | } 629 | 630 | ms = mlfi_eom((SMFICTX *) tctx); 631 | if (MLFI_OUTPUT(ms, tverbose)) 632 | { 633 | fprintf(stderr, "%s: %s: mlfi_eom() returned %s\n", 634 | progname, file, milter_status[ms]); 635 | } 636 | 637 | return EX_OK; 638 | } 639 | 640 | /* 641 | ** ARCF_TESTFILES -- test one or more input messages 642 | ** 643 | ** Parameters: 644 | ** libopenarc -- ARC_LIB handle 645 | ** flist -- input file list 646 | ** verbose -- verbose level 647 | ** 648 | ** Return value: 649 | ** An EX_* constant (see sysexits.h) 650 | */ 651 | 652 | int 653 | arcf_testfiles(ARC_LIB *libopenarc, char *flist, int verbose) 654 | { 655 | char *file; 656 | char *ctx; 657 | FILE *f; 658 | int status; 659 | sfsistat ms; 660 | struct test_context *tctx; 661 | struct sockaddr_in sin; 662 | 663 | assert(libopenarc != NULL); 664 | assert(flist != NULL); 665 | 666 | tverbose = verbose; 667 | 668 | /* set up a fake SMFICTX */ 669 | tctx = (struct test_context *) malloc(sizeof(struct test_context)); 670 | if (tctx == NULL) 671 | { 672 | fprintf(stderr, "%s: malloc(): %s\n", progname, 673 | strerror(errno)); 674 | return EX_OSERR; 675 | } 676 | tctx->tc_priv = NULL; 677 | 678 | (void) memset(&sin, '\0', sizeof sin); 679 | sin.sin_family = AF_INET; 680 | sin.sin_port = htons(time(NULL) % 65536); 681 | sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 682 | 683 | ms = mlfi_connect((SMFICTX *) tctx, "localhost", (_SOCK_ADDR *) &sin); 684 | if (MLFI_OUTPUT(ms, tverbose)) 685 | { 686 | fprintf(stderr, "%s: mlfi_connect() returned %s\n", 687 | progname, milter_status[ms]); 688 | } 689 | if (ms != SMFIS_CONTINUE) 690 | return EX_SOFTWARE; 691 | 692 | /* loop through inputs */ 693 | for (file = strtok_r(flist, ",", &ctx); 694 | file != NULL; 695 | file = strtok_r(NULL, ",", &ctx)) 696 | { 697 | /* open the input */ 698 | if (strcmp(file, "-") == 0) 699 | { 700 | f = stdin; 701 | file = "(stdin)"; 702 | } 703 | else 704 | { 705 | f = fopen(file, "r"); 706 | if (f == NULL) 707 | { 708 | fprintf(stderr, "%s: %s: fopen(): %s\n", 709 | progname, file, strerror(errno)); 710 | return EX_UNAVAILABLE; 711 | } 712 | } 713 | 714 | status = arcf_testfile(libopenarc, tctx, f, file, tverbose); 715 | 716 | FCLOSE(f); 717 | 718 | if (status != EX_OK) 719 | return status; 720 | } 721 | 722 | ms = mlfi_close((SMFICTX *) tctx); 723 | if (MLFI_OUTPUT(ms, tverbose)) 724 | { 725 | fprintf(stderr, "%s: mlfi_close() returned %s\n", 726 | progname, milter_status[ms]); 727 | } 728 | 729 | return EX_OK; 730 | } 731 | -------------------------------------------------------------------------------- /openarc/openarc-test.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2007 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2012, The Trusted Domain Project. All rights reserved. 6 | ** 7 | */ 8 | 9 | #ifndef _TEST_H_ 10 | #define _TEST_H_ 11 | 12 | /* system includes */ 13 | #include 14 | #include 15 | 16 | /* libmilter includes */ 17 | #include 18 | 19 | /* libopenarc includes */ 20 | #include "arc.h" 21 | 22 | /* PROTOTYPES */ 23 | extern int arcf_testfiles __P((ARC_LIB *, char *, int)); 24 | 25 | extern int arcf_test_addheader __P((void *, char *, char *)); 26 | extern int arcf_test_addrcpt __P((void *, char *)); 27 | extern int arcf_test_chgheader __P((void *, char *, int, char *)); 28 | extern int arcf_test_delrcpt __P((void *, char *)); 29 | extern void *arcf_test_getpriv __P((void *)); 30 | extern char *arcf_test_getsymval __P((void *, char *)); 31 | extern int arcf_test_insheader __P((void *, int, char *, char *)); 32 | extern int arcf_test_progress __P((void *)); 33 | extern int arcf_test_quarantine __P((void *, char *)); 34 | extern int arcf_test_setpriv __P((void *, void *)); 35 | extern int arcf_test_setreply __P((void *, char *, char *, char *)); 36 | 37 | #endif /* _TEST_H_ */ 38 | -------------------------------------------------------------------------------- /openarc/openarc.8.in: -------------------------------------------------------------------------------- 1 | .TH openarc 8 "The Trusted Domain Project" 2 | .SH NAME 3 | .B openarc 4 | \- ARC signing and verifying filter for MTAs 5 | .SH SYNOPSIS 6 | .B openarc 7 | [\-c configfile] 8 | [\-f] 9 | [\-n] 10 | [\-p socketspec] 11 | [\-P pidfile] 12 | [\-u userid[:group]] 13 | [\-v] 14 | [\-V] 15 | .SH DESCRIPTION 16 | .B openarc 17 | implements the proposed 18 | .B ARC 19 | (Authenticated Received Chain) standard for confirming handling and 20 | authentication of a message as it is handled for delivery. 21 | 22 | .B openarc 23 | uses the 24 | .I milter 25 | interface, originally distributed as part of version 8.11 of 26 | .B sendmail(8), 27 | to provide ARC signing and/or verifying service for mail transiting 28 | a milter-aware MTA. 29 | .SH OPTIONS 30 | .TP 31 | .I \-c configfile 32 | Read the named configuration file. See the 33 | .I openarc.conf(5) 34 | man page for details. Values in the configuration file are overridden 35 | when their equivalents are provided on the command line until a configuration 36 | reload occurs. The default is to read a configuration file from 37 | .I @SYSCONFDIR@/openarc.conf 38 | if one exists, or otherwise to apply defaults to all values. 39 | .TP 40 | .I \-f 41 | Normally 42 | .I openarc 43 | forks and exits immediately, leaving the service running in the background. 44 | This flag suppresses that behaviour so that it runs in the foreground. 45 | .TP 46 | .I \-n 47 | Parse the configuration file and command line arguments, reporting any 48 | errors found, and then exit. The exit value will be 0 if the filter would 49 | start up without complaint, or non-zero otherwise. 50 | .TP 51 | .I \-p socketspec 52 | Specifies the socket that should be established by the filter to receive 53 | connections from 54 | .I sendmail(8) 55 | in order to provide service. 56 | .I socketspec 57 | is in one of two forms: 58 | .I local:path 59 | which creates a UNIX domain socket at the specified 60 | .I path, 61 | or 62 | .I inet:port[@host] 63 | or 64 | .I inet6:port[@host] 65 | which creates a TCP socket on the specified 66 | .I port 67 | using the requested protocol family. If the 68 | .I host 69 | is not given as either a hostname or an IP address, the socket will be 70 | listening on all interfaces. A literal IP address must be enclosed in 71 | square brackets. If neither socket type is specified, 72 | .I local 73 | is assumed, meaning the parameter is interpreted as a path at which 74 | the socket should be created. This parameter is mandatory either here or 75 | in the configuration file. 76 | .TP 77 | .I \-P pidfile 78 | Specifies a file into which the filter should write its process ID at startup. 79 | .TP 80 | .I \-u userid[:group] 81 | Attempts to be come the specified 82 | .I userid 83 | before starting operations. The process will be assigned all of the groups 84 | and primary group ID of the named 85 | .I userid 86 | unless an alternate 87 | .I group 88 | is specified. See the FILE PERMISSIONS section for more information. 89 | .TP 90 | .I \-V 91 | Print the version number and build-time options, and then exit without 92 | doing anything else. 93 | .SH EXIT STATUS 94 | Filter exit status codes are selected according to 95 | .I sysexits(3). 96 | .SH VERSION 97 | This man page covers version @VERSION@ of 98 | .I openarc. 99 | .SH COPYRIGHT 100 | Copyright (c) 2005-2008, Sendmail, Inc. and its suppliers. All rights 101 | reserved. 102 | 103 | Copyright (c) 2009-2013, 2015, 2016, The Trusted Domain Project. 104 | All rights reserved. 105 | .SH SEE ALSO 106 | .I openarc.conf(5), sendmail(8) 107 | .P 108 | Sendmail Operations Guide 109 | .P 110 | RFC5321 - Simple Mail Transfer Protocol 111 | .P 112 | RFC5322 - Internet Messages 113 | .P 114 | RFC7601 - Message Header Field for Indicating Message Authentication Status 115 | .P 116 | -------------------------------------------------------------------------------- /openarc/openarc.conf.5.in: -------------------------------------------------------------------------------- 1 | .TH openarc.conf 5 "The Trusted Domain Project" 2 | 3 | .SH NAME 4 | .B openarc.conf 5 | \- Configuration file for openarc 6 | 7 | .SH LOCATION 8 | .I @SYSCONFDIR@/openarc.conf 9 | 10 | .SH DESCRIPTION 11 | .I openarc(8) 12 | implements the 13 | .B ARC 14 | (Authenticated Received Chain) 15 | specification for verifying authentication and handling of messages as 16 | they are routed to their destinations. This file is its configuration file. 17 | 18 | Blank lines are ignored. Lines containing a hash ("#") character are 19 | truncated at the hash character to allow for comments in the file. 20 | 21 | Other content should be the name of a parameter, followed by white space, 22 | followed by the value of that parameter, each on a separate line. 23 | 24 | For parameters that are Boolean in nature, only the first byte of 25 | the value is processed. For positive values, the following are accepted: 26 | "T", "t", "Y", "y", "1". For negative values, the following are accepted: 27 | "F", "f", "N", "n", "0". 28 | 29 | See the 30 | .I openarc(8) 31 | man page for details about how and when the configuration file contents 32 | are reloaded. 33 | 34 | Unless otherwise stated, Boolean values default to "false", integer values 35 | default to 0, and string and dataset values default to being undefined. 36 | 37 | .SH PARAMETERS 38 | .TP 39 | .I AutoRestart (Boolean) 40 | Automatically re-start on failures. Use with caution; if the filter 41 | fails instantly after it starts, this can cause a tight 42 | .I fork(2) 43 | loop. 44 | 45 | .TP 46 | .I AutoRestartCount (integer) 47 | Sets the maximum automatic restart count. After this number of 48 | automatic restarts, the filter will give up and terminate. 49 | A value of 0 implies no limit; this is the default. 50 | 51 | .TP 52 | .I AutoRestartRate (string) 53 | Sets the maximum automatic restart rate. If the filter begins restarting 54 | faster than the rate defined here, it will give up and terminate. 55 | This is a string of the form 56 | .I n/t[u] 57 | where 58 | .I n 59 | is an integer limiting the count of restarts in the given interval and 60 | .I t[u] 61 | defines the time interval through which the rate is calculated; 62 | .I t 63 | is an integer and 64 | .I u 65 | defines the units thus represented ("s" or "S" for seconds, the default; 66 | "m" or "M" for minutes; "h" or "H" for hours; "d" or "D" for days). For 67 | example, a value of "10/1h" limits the restarts to 10 in one hour. There 68 | is no default, meaning restart rate is not limited. 69 | 70 | .TP 71 | .I Background (Boolean) 72 | Causes 73 | .I openarc 74 | to fork and exits immediately, leaving the service running in the background. 75 | The default is "true". 76 | 77 | .TP 78 | .I Canonicalization (string) 79 | Selects the canonicalization method(s) to be used when signing messages. 80 | When verifying, the message's ARC-Message-Signature: header field specifies 81 | the canonicalization method. The recognized values are 82 | .I relaxed 83 | and 84 | .I simple 85 | as defined by the DKIM specification. The default is 86 | .I relaxed/simple. 87 | The value may include two different canonicalizations separated by a 88 | slash ("/") character, in which case the first will be applied to the 89 | header and the second to the body. 90 | 91 | .TP 92 | .I ChangeRootDirectory (string) 93 | Requests that the operating system change the effective root directory 94 | of the process to the one specified here prior to beginning execution. 95 | .BR chroot (2) 96 | requires superuser access. A warning will be generated if 97 | .I UserID 98 | is not also set. 99 | 100 | .TP 101 | .I EnableCoredumps (boolean) 102 | On systems that have such support, make an explicit request to the kernel 103 | to dump cores when the filter crashes for some reason. Some modern UNIX 104 | systems suppress core dumps during crashes for security reasons if the 105 | user ID has changed during the lifetime of the process. Currently only 106 | supported on Linux. 107 | 108 | .TP 109 | .I Include (string) 110 | Names a file to be opened and read as an additional configuration file. 111 | Nesting is allowed to a maximum of five levels. 112 | 113 | .TP 114 | .I InternalHosts (dataset) 115 | Identifies a set of hosts that identifies clients whose connections 116 | should be treated as "internal" by this filter. Messages received from 117 | such sources will not be verified and are instead trusted as-is; in 118 | particular, their Authentication-Results fields are trusted to be 119 | correct and authentic, meaning they will be assumed to contain the correct 120 | chain status when generating an outgoing seal. See the description of 121 | "PeerList" for a description of the supported format. If no set is 122 | provided, "127.0.0.1" is added to the list by default. 123 | 124 | .TP 125 | .I MilterDebug (integer) 126 | Sets the debug level to be requested from the milter library. The 127 | default is 0. 128 | 129 | .TP 130 | .I Mode (string) 131 | Selects the operating mode(s) for this filter. If the string contains 132 | the character "s", the filter will sign and seal messages passing through 133 | the filter. If the string contains the character "v", the filter 134 | will do signature and seal validation of arriving messages. The two 135 | can be combined. If neither is specified, the operating mode will 136 | be inferred on a per-connection basis based on the entries in the 137 | .I InternalHosts 138 | list; connections from internal hosts will be assigned to signing mode, 139 | and all others will be assigned to verify mode. 140 | 141 | .TP 142 | .I OversignHeaders (string) 143 | Specifies a comma-separated list of header field names that should be 144 | included in all signature header lists (the "h=" tag) once more than the 145 | number of times they were actually present in the signed message. The set 146 | is empty by default. The purpose of this, and especially of listing an 147 | absent header field, is to prevent the addition of important fields between 148 | the signer and the verifier. Since the verifier would include that header 149 | field when performing verification if it had been added by an intermediary, 150 | the signed message and the verified message were different and the 151 | verification would fail. Note that listing a field name here and not listing 152 | it in the 153 | .I SignHeaders 154 | list is likely to generate invalid signatures. 155 | 156 | .TP 157 | .I PeerList (dataset) 158 | Identifies a set of "peers" that identifies clients whose connections 159 | should be accepted without processing by this filter. The set 160 | should contain on each line a hostname, domain name (e.g. ".example.com"), 161 | IP address, an IPv6 address (including an IPv4 mapped address), or a 162 | CIDR-style IP specification (e.g. "192.168.1.0/24"). An entry beginning 163 | with a bang ("!") character means "not", allowing exclusions of specific 164 | hosts that are otherwise members of larger sets. Host and domain names are 165 | matched first, then the IP or IPv6 address depending on the connection 166 | type. More precise entries are preferred over less precise ones, i.e. 167 | "192.168.1.1" will match before "!192.168.1.0/24". The text form of IPv6 168 | addresses will be forced to lowercase when queried (RFC5952), so the contents 169 | of this data set should also use lowercase. The IP address portion of an 170 | entry may optionally contain square brackets; both forms (with and without) 171 | will be checked. 172 | 173 | .TP 174 | .I PidFile (string) 175 | Specifies the path to a file that should be created at process start 176 | containing the process ID. 177 | 178 | .TP 179 | .I SignatureAlgorithm (string) 180 | Selects the signing algorithm to use when generating signatures. 181 | Use 'openarc \-V' to see the list of supported algorithms. 182 | The default is 183 | .I rsa-sha256. 184 | 185 | .TP 186 | .I SignHeaders (string) 187 | Specifies the set of header fields that should be included when generating 188 | signatures. This is expected to be a comma-separated list of header 189 | field names, and matching is case-insensitive. If the list omits any header 190 | field that is mandated by the ARC specification, those fields are implicitly 191 | added. By default, those fields listed in the DKIM specification as 192 | "SHOULD" be signed (RFC6376, Section 5.4) will be signed by the filter. 193 | 194 | .TP 195 | .I Socket (string) 196 | Specifies the socket that should be established by the filter to receive 197 | connections from 198 | .I sendmail(8) 199 | in order to provide service. 200 | .I socketspec 201 | is in one of two forms: 202 | .I local:path, 203 | which creates a UNIX domain socket at the specified 204 | .I path, 205 | or 206 | .I inet:port[@host] 207 | or 208 | .I inet6:port[@host] 209 | which creates a TCP socket on the specified 210 | .I port 211 | and in the specified protocol family. If the 212 | .I host 213 | is not given as either a hostname or an IP address, the socket will be 214 | listening on all interfaces. A literal IP address must be enclosed in 215 | square brackets. This option is mandatory either in the configuration file or 216 | on the command line. 217 | 218 | .TP 219 | .I Syslog (Boolean) 220 | Log via calls to 221 | .I syslog(3) 222 | any interesting activity. 223 | 224 | .TP 225 | .I SyslogFacility (string) 226 | Log via calls to 227 | .I syslog(3) 228 | using the named facility. The facility names are the same as the ones 229 | allowed in 230 | .I syslog.conf(5). 231 | The default is "mail". 232 | 233 | .TP 234 | .I UserID (string) 235 | Attempts to become the specified userid before starting operations. 236 | The value is of the form 237 | .I userid[:group]. 238 | The process will be assigned all of the groups and primary group ID of 239 | the named 240 | .I userid 241 | unless an alternate 242 | .I group 243 | is specified. 244 | 245 | .SH NOTES 246 | Features that involve specification of IPv4 addresses or CIDR blocks 247 | will use the 248 | .I inet_addr(3) 249 | function to parse that information. Users should be familiar with the 250 | way that function handles the non-trivial cases (for example, "192.0.2/24" 251 | and "192.0.2.0/24" are not the same thing). 252 | .SH FILES 253 | .TP 254 | .I @SYSCONFDIR@/openarc.conf 255 | Default location of this file. 256 | .SH VERSION 257 | This man page covers version @VERSION@ of 258 | .I openarc. 259 | 260 | .SH COPYRIGHT 261 | Copyright (c) 2007, 2008, Sendmail, Inc. and its suppliers. All rights 262 | reserved. 263 | 264 | Copyright (c) 2009-2017, The Trusted Domain Project. All rights reserved. 265 | .SH SEE ALSO 266 | .I openarc(8), sendmail(8) 267 | .P 268 | RFC5451 - Message Header Field for Indicating Message Authentication Status 269 | .P 270 | RFC5617 - DKIM Author Domain Signing Practises 271 | .P 272 | RFC5965 - An Extensible Format for Email Feedback Reports 273 | .P 274 | RFC6008 - Authentication-Results Registration for Differentiating among 275 | Cryptographic Results 276 | .P 277 | RFC6376 - DomainKeys Identified Mail 278 | .P 279 | RFC6651 - Extensions to DomainKeys Identified Mail (DKIM) for Failure Reporting 280 | -------------------------------------------------------------------------------- /openarc/openarc.conf.sample: -------------------------------------------------------------------------------- 1 | ## 2 | ## openarc.conf -- configuration file for OpenARC filter 3 | ## 4 | ## Copyright (c) 2010-2015, 2017, The Trusted Domain Project. 5 | ## All rights reserved. 6 | ## 7 | 8 | ## CONFIGURATION OPTIONS 9 | 10 | ## AuthservID string 11 | ## default (local host name) 12 | ## 13 | ## Defines the "authserv-id" token to be used when generating 14 | ## Authentication-Results headers after message verification. 15 | 16 | # AuthservID example.com 17 | 18 | ## AutoRestart { yes | no } 19 | ## default "no" 20 | ## 21 | ## Indicate whether or not the filter should arrange to restart automatically 22 | ## if it crashes. 23 | 24 | # AutoRestart No 25 | 26 | ## AutoRestartCount n 27 | ## default 0 28 | ## 29 | ## Sets the maximum automatic restart count. After this number of 30 | ## automatic restarts, the filter will give up and terminate. A value of 0 31 | ## implies no limit. 32 | 33 | # AutoRestartCount 0 34 | 35 | ## AutoRestartRate n/t[u] 36 | ## default (none) 37 | ## 38 | ## Sets the maximum automatic restart rate. See the opendkim.conf(5) 39 | ## man page for the format of this parameter. 40 | 41 | # AutoRestartRate n/tu 42 | 43 | ## Background { yes | no } 44 | ## default "yes" 45 | ## 46 | ## Indicate whether or not the filter should run in the background. 47 | 48 | # Background Yes 49 | 50 | ## BaseDirectory path 51 | ## default (none) 52 | ## 53 | ## Causes the filter to change to the named directory before beginning 54 | ## operation. Thus, cores will be dumped here and configuration files 55 | ## are read relative to this location. 56 | 57 | # BaseDirectory /var/run/opendkim 58 | 59 | ## Canonicalization hdrcanon[/bodycanon] 60 | ## default "simple/simple" 61 | ## 62 | ## Select canonicalizations to use when signing. If the "bodycanon" is 63 | ## omitted, "simple" is used. Valid values for each are "simple" and 64 | ## "relaxed". 65 | 66 | # Canonicalization simple/simple 67 | 68 | ## ChangeRootDirectory directory 69 | ## 70 | ## Changes to the specified directory before beginning execution. 71 | 72 | # ChangeRootDirectory dirname 73 | 74 | ## Domain domain-name 75 | ## default (none) 76 | ## 77 | ## Specify the domain to use when generating ARC header fields. Must 78 | ## be specified for signing. 79 | 80 | Domain example.com 81 | 82 | ## EnableCoredumps { yes | no } 83 | ## default "no" 84 | ## 85 | ## On systems which have support for such, requests that the kernel dump 86 | ## core even though the process may change user ID during its execution. 87 | 88 | # EnableCoredumps no 89 | 90 | ## FixedTimestamp timestamp 91 | ## default (none) 92 | ## 93 | ## Forces a specific timestamp to be used when generating ARC header fields. 94 | ## By default, uses the current time. 95 | 96 | # FixedTimestamp 1234567890 97 | 98 | ## InternalHosts file 99 | ## default (none) 100 | ## 101 | ## Names a file that contains a list of IP addresses, CIDR blocks, hostnames 102 | ## or domain names whose mail should be considered to have come from an 103 | ## internal trusted source, and thus authentication details found in the 104 | ## message will be used as-is. See man page for file format. 105 | 106 | # InternalHosts filename 107 | 108 | ## KeepTemporaryFiles { yes | no } 109 | ## default "no" 110 | ## 111 | ## If set, causes temporary files generated during message signing or 112 | ## verifying to be left behind for debugging use. Not for normal operation; 113 | ## can fill your disks quite fast on busy systems. 114 | 115 | # KeepTemporaryFiles no 116 | 117 | ## KeyFile filename 118 | ## default (none) 119 | ## 120 | ## Specifies the path to the private key to use when signing. Ignored if 121 | ## SigningTable and KeyTable are used. No default; must be specified for 122 | ## signing if SigningTable/KeyTable are not in use. 123 | 124 | KeyFile /var/db/dkim/example.private 125 | 126 | ## MaximumHeaders n 127 | ## 128 | ## Disallow messages whose header blocks are bigger than "n" bytes. 129 | ## Intended to detect and block a denial-of-service attack. The default 130 | ## is 65536. A value of 0 disables this test. 131 | 132 | # MaximumHeaders n 133 | 134 | ## MilterDebug n 135 | ## 136 | ## Request a debug level of "n" from the milter library. The default is 0. 137 | 138 | # MilterDebug 0 139 | 140 | ## Mode modes 141 | ## default (none) 142 | ## 143 | ## Selects the operating mode(s) for this filter. If the string contains 144 | ## the character "s", the filter will sign and seal messages passing through 145 | ## the filter. If the string contains the character "v", the filter 146 | ## will do signature and seal validation of arriving messages. The two 147 | ## can be combined. If neither is specified, the operating mode will 148 | ## be inferred on a per-connection basis based on the entries in the 149 | ## InternalHosts list; connections from internal hosts will be assigned to 150 | ## signing mode, and all others will be assigned to verify mode. 151 | 152 | # Mode sv 153 | 154 | ## OversignHeaders (string) 155 | ## default (none) 156 | ## 157 | ## Specifies the set of header fields that should be "oversigned" when 158 | ## generating signatures. The string should be a comma-separated list of 159 | ## header field names. See the openarc.conf(5) man page for details. 160 | 161 | # OversignHeaders header1,header2,... 162 | 163 | ## PeerList file 164 | ## default (none) 165 | ## 166 | ## Names a file that contains a list of IP addresses, CIDR blocks, hostnames 167 | ## or domain names whose mail should be neither signed nor verified by this 168 | ## filter. See man page for file format. 169 | 170 | # PeerList filename 171 | 172 | ## PidFile filename 173 | ## default (none) 174 | ## 175 | ## Name of the file where the filter should write its pid before beginning 176 | ## normal operations. 177 | 178 | # PidFile filename 179 | 180 | ## Selector name 181 | ## 182 | ## The name of the selector to use when signing. No default; must be 183 | ## specified for signing. 184 | 185 | Selector my-selector-name 186 | 187 | ## SignatureAlgorithm signalg 188 | ## default "rsa-sha256" 189 | ## 190 | ## Signature algorithm to use when generating signatures. Must be either 191 | ## "rsa-sha1" or "rsa-sha256". 192 | 193 | # SignatureAlgorithm rsa-sha256 194 | 195 | ## SignHeaders (string) 196 | ## default (none) 197 | ## 198 | ## Specifies the set of header fields that should be included when generating 199 | ## signatures. The string should be a comma-separated list of header field 200 | ## names. 201 | 202 | # SignHeaders header1,header2,... 203 | 204 | ## Socket socketspec 205 | ## 206 | ## Names the socket where this filter should listen for milter connections 207 | ## from the MTA. Required. Should be in one of these forms: 208 | ## 209 | ## inet:port@address to listen on a specific interface 210 | ## inet:port to listen on all interfaces 211 | ## local:/path/to/socket to listen on a UNIX domain socket 212 | 213 | Socket inet:port@localhost 214 | 215 | ## SoftwareHeader { yes | no } 216 | ## default "no" 217 | ## 218 | ## Add an ARC-Filter header field to messages passing through this filter 219 | ## to identify messages it has processed. 220 | 221 | # SoftwareHeader no 222 | 223 | ## Syslog { yes | no } 224 | ## default "yes" 225 | ## 226 | ## Log informational and error activity to syslog? 227 | 228 | Syslog Yes 229 | 230 | ## SyslogFacility facility 231 | ## default "mail" 232 | ## 233 | ## Valid values are : 234 | ## auth cron daemon kern lpr mail news security syslog user uucp 235 | ## local0 local1 local2 local3 local4 local5 local6 local7 236 | ## 237 | ## syslog facility to be used 238 | 239 | # SyslogFacility mail 240 | 241 | ## TemporaryDirectory path 242 | ## default /tmp 243 | ## 244 | ## Specifies which directory will be used for creating temporary files 245 | ## during message processing. 246 | 247 | # TemporaryDirectory /tmp 248 | 249 | ## Userid userid 250 | ## default (none) 251 | ## 252 | ## Change to user "userid" before starting normal operation? May include 253 | ## a group ID as well, separated from the userid by a colon. 254 | 255 | # UserID userid 256 | -------------------------------------------------------------------------------- /openarc/openarc.conf.simple.in: -------------------------------------------------------------------------------- 1 | # This is a simple config file for OpenARC 2 | 3 | Mode sv 4 | 5 | Syslog yes 6 | 7 | Socket inet:8891@localhost 8 | 9 | # PidFile /var/run/opendkim/opendkim.pid 10 | -------------------------------------------------------------------------------- /openarc/openarc.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2005-2009 Sendmail, Inc. and its suppliers. 3 | ** All rights reserved. 4 | ** 5 | ** Copyright (c) 2009-2014, 2016, The Trusted Domain Project. 6 | ** All rights reserved. 7 | */ 8 | 9 | #ifndef _OPENARC_H_ 10 | #define _OPENARC_H_ 11 | 12 | #define ARCF_PRODUCT "OpenARC Filter" 13 | #define ARCF_PRODUCTNS "OpenARC-Filter" 14 | 15 | #include "build-config.h" 16 | 17 | /* system includes */ 18 | #include 19 | #ifdef HAVE_STDBOOL_H 20 | # include 21 | #endif /* HAVE_STDBOOL_H */ 22 | 23 | /* libmilter */ 24 | #ifdef ARCF_MILTER_PROTOTYPES 25 | # include 26 | #endif /* ARCF_MILTER_PROTOTYPES */ 27 | 28 | /* libopenarc */ 29 | #include "arc.h" 30 | 31 | /* make sure we have TRUE and FALSE */ 32 | #ifndef FALSE 33 | # define FALSE 0 34 | #endif /* !FALSE */ 35 | #ifndef TRUE 36 | # define TRUE 1 37 | #endif /* !TRUE */ 38 | 39 | /* defaults, limits, etc. */ 40 | #define BUFRSZ 1024 41 | #define CONFIGOPTS "Ac:flnp:P:rt:u:vV" 42 | #define DEFCONFFILE CONFIG_BASE "/openarc.conf" 43 | #define DEFINTERNAL "csl:127.0.0.1,::1" 44 | #define DEFMAXHDRSZ 65536 45 | #define HOSTUNKNOWN "unknown-host" 46 | #define JOBIDUNKNOWN "(unknown-jobid)" 47 | #define LOCALHOST "127.0.0.1" 48 | #define MAXADDRESS 256 49 | #define MAXARGV 65536 50 | #define MAXBUFRSZ 65536 51 | #define MAXHDRCNT 64 52 | #define MAXHDRLEN 78 53 | #define MAXSIGNATURE 1024 54 | #define MTAMARGIN 78 55 | #define NULLDOMAIN "(invalid)" 56 | #define UNKNOWN "unknown" 57 | 58 | #define AUTHRESULTSHDR "Authentication-Results" 59 | #define SWHEADERNAME "ARC-Filter" 60 | 61 | /* 62 | ** HEADER -- a handle referring to a header 63 | */ 64 | 65 | typedef struct Header * Header; 66 | struct Header 67 | { 68 | char * hdr_hdr; 69 | char * hdr_val; 70 | struct Header * hdr_next; 71 | struct Header * hdr_prev; 72 | }; 73 | 74 | /* externs */ 75 | extern _Bool dolog; 76 | extern char *progname; 77 | 78 | /* prototypes, exported for test.c */ 79 | extern ARC_MESSAGE *arcf_getarc __P((void *)); 80 | 81 | #ifdef ARCF_MILTER_PROTOTYPES 82 | extern sfsistat mlfi_connect __P((SMFICTX *, char *, _SOCK_ADDR *)); 83 | extern sfsistat mlfi_envfrom __P((SMFICTX *, char **)); 84 | extern sfsistat mlfi_envrcpt __P((SMFICTX *, char **)); 85 | extern sfsistat mlfi_header __P((SMFICTX *, char *, char *)); 86 | extern sfsistat mlfi_eoh __P((SMFICTX *)); 87 | extern sfsistat mlfi_body __P((SMFICTX *, u_char *, size_t)); 88 | extern sfsistat mlfi_eom __P((SMFICTX *)); 89 | extern sfsistat mlfi_abort __P((SMFICTX *)); 90 | extern sfsistat mlfi_close __P((SMFICTX *)); 91 | #endif /* ARCF_MILTER_PROTOTYPES */ 92 | 93 | #endif /* _OPENARC_H_ */ 94 | -------------------------------------------------------------------------------- /openarc/tests/Makefile.am: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/trusteddomainproject/OpenARC/355ee2a1ca85acccce494478991983b54f794f4e/openarc/tests/Makefile.am -------------------------------------------------------------------------------- /openarc/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | ** Copyright (c) 2016, 2017, The Trusted Domain Project. 3 | ** All rights reserved. 4 | */ 5 | 6 | #ifndef _UTIL_H_ 7 | #define _UTIL_H_ 8 | 9 | /* system includes */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* openarc includes */ 17 | #include "build-config.h" 18 | 19 | /* TYPES */ 20 | struct arcf_dstring; 21 | 22 | /* PROTOTYPES */ 23 | extern const char **arcf_mkarray __P((char *)); 24 | extern size_t arcf_inet_ntoa __P((struct in_addr, char *, size_t)); 25 | extern void arcf_lowercase __P((u_char *)); 26 | extern void arcf_optlist __P((FILE *)); 27 | extern void arcf_setmaxfd __P((void)); 28 | extern int arcf_socket_cleanup __P((char *)); 29 | 30 | extern struct arcf_dstring *arcf_dstring_new __P((int, int)); 31 | extern void arcf_dstring_free __P((struct arcf_dstring *)); 32 | extern _Bool arcf_dstring_copy __P((struct arcf_dstring *, u_char *)); 33 | extern _Bool arcf_dstring_cat __P((struct arcf_dstring *, u_char *)); 34 | extern _Bool arcf_dstring_cat1 __P((struct arcf_dstring *, int)); 35 | extern _Bool arcf_dstring_catn __P((struct arcf_dstring *, u_char *, size_t)); 36 | extern void arcf_dstring_chop __P((struct arcf_dstring *, int)); 37 | extern u_char *arcf_dstring_get __P((struct arcf_dstring *)); 38 | extern int arcf_dstring_len __P((struct arcf_dstring *)); 39 | extern void arcf_dstring_blank __P((struct arcf_dstring *)); 40 | extern size_t arcf_dstring_printf __P((struct arcf_dstring *, char *, ...)); 41 | 42 | #endif /* _UTIL_H_ */ 43 | --------------------------------------------------------------------------------